예제 #1
0
 def test_missing_elements(self):
     req_parser = GeoproxyRequestParser(None, None)
     out = req_parser.find_missing_elements([1, 2, 3], [2])
     self.assertEqual(out, [1, 3])
     out = req_parser.find_missing_elements([1, 2, 3], [1, 2, 3])
     self.assertEqual(out, [])
     out = req_parser.find_missing_elements([1, 2, 3], [1, 2, 3, 4])
     self.assertEqual(out, [])
예제 #2
0
 def test_bad_parse(self):
     invalid = {"service": ["google"], "bounds": ["1.0,2.0|3.0,4.0"]}
     mock_handler = MockRequestHandler(invalid)
     response = GeoproxyResponse()
     mock_services = {"google": None, "here": None}
     req_parser = GeoproxyRequestParser(mock_services, response)
     out = req_parser.parse(mock_handler)
     # missing address
     self.assertFalse(out)
     self.assertEqual(response.status, "INVALID_REQUEST")
예제 #3
0
 def test_bad_parse2(self):
     invalid = {"address": ["Addr"], "service": ["blah"], "bounds": ["1.0,2.0|3.0,4.0"]}
     mock_handler = MockRequestHandler(invalid)
     response = GeoproxyResponse()
     mock_services = {"google": None, "here": None}
     req_parser = GeoproxyRequestParser(mock_services, response)
     out = req_parser.parse(mock_handler)
     self.assertTrue(out)
     # invalid primary service
     self.assertTrue(all(elem in req_parser.services for elem in ["google", "here"]))
     self.assertEqual(response.query, "Addr")
예제 #4
0
 def test_here_parse(self):
     valid = {"address": ["Addr"], "service": ["here"], "bounds": ["1.0,2.0|3.0,4.0"]}
     mock_handler = MockRequestHandler(valid)
     response = GeoproxyResponse()
     mock_services = {"google": None, "here": None}
     req_parser = GeoproxyRequestParser(mock_services, response)
     out = req_parser.parse(mock_handler)
     self.assertTrue(out)
     self.assertEqual(req_parser.address, "Addr")
     self.assertEqual(req_parser.services, ["here", "google"])
     self.assertEqual(req_parser.bounds.top_left.latitude, 3.0)
예제 #5
0
 def test_request_parser_constructor(self):
     response = GeoproxyResponse()
     mock_services = {"google": None, "here": None}
     req_parser = GeoproxyRequestParser(mock_services, response)
     self.assertEqual(len(req_parser.services), 0)
     self.assertEqual(req_parser.available_services, mock_services)
     self.assertEqual(req_parser.geo_proxy_response, response)
예제 #6
0
 def test_parse_bounding_coordinates(self):
     req_parser = GeoproxyRequestParser(None, None)
     # way wrong
     self.assertIsNone(req_parser.parse_bounding_coordinates("Bad"))
     # not enough coords
     self.assertIsNone(req_parser.parse_bounding_coordinates("1.0,2.0"))
     # too many coords
     self.assertIsNone(req_parser.parse_bounding_coordinates("1.0,2.0|1.0,2.0|1.0,2.0"))
     # wrong delim
     self.assertIsNone(req_parser.parse_bounding_coordinates("1.0,2.0;1.0,2.0"))
     # wrong num lat/long
     self.assertIsNone(req_parser.parse_bounding_coordinates("1.0,2.0,3.0|1.0,2.0"))
     # right
     out = req_parser.parse_bounding_coordinates("1.0,2.0|3.0,4.0")
     self.assertIsNotNone(out)
     self.assertEqual(len(out), 4)
     self.assertEqual(out[1], 2.0)
예제 #7
0
    def get(self):
        """Request handler for method=GET

        Responsible for spawning third party geocoder query tasks based on parsed request data

        Pseudo code:
        - Create empty response
        - Parse incoming request
        - If parse success:
            - For each third party service:
                - Build third party service query from incoming request data
                - Spawn query task and wait on future for third party response
                - Parse third party response
                - If success:
                    - Set response result
                    - Break
                - Next service in loop
        - Else:
            - Set response error
        - Send response

        """
        start_time = time.time()
        # Create an empty API response
        geo_proxy_response = GeoproxyResponse()

        try:
            # Next, parse the inputs from the RESTful query and ensure they are all valid
            geo_proxy_request = GeoproxyRequestParser(self.available_services,
                                                      geo_proxy_response)
            # if our request parse succeeds, we have valid input data and can proceed
            if geo_proxy_request.parse(self):
                self.logger.info(
                    "Incoming request:\n{}".format(geo_proxy_request))
                # iterate through each service in request.services until we get a successful result
                for service in geo_proxy_request.services:
                    self.logger.info(
                        "Querying third-party service: {}".format(service))
                    # Grab the third party helper object, associated with the service
                    # The helper assists with third party query construction and parsing
                    service_helper = self.available_services[service]
                    # build the third party query based on our request inputs
                    service_helper.build_query(geo_proxy_request.address,
                                               geo_proxy_request.bounds)
                    # run the query and yield the response
                    response_json = yield self.query_third_party_geocoder(
                        service_helper.query)
                    if response_json:
                        # if we got a valid response from the third party query, parse it!
                        parse_success = service_helper.parser.parse(
                            response_json)
                        # fragile detection if there was a valid response, but zero results
                        if parse_success == 0:
                            geo_proxy_response.set_error(
                                "Zero results", "ZERO_RESULTS")
                        # otherwise assume the parse was successful, and we extracted data
                        # package it into our response object to be sent out.
                        elif parse_success is not None:
                            geo_proxy_response.error = None
                            geo_proxy_response.set_result(
                                service, service_helper.parser.latitude,
                                service_helper.parser.longitude,
                                service_helper.parser.address)
                            # if we get a valid result, don't keep querying the other third
                            # party services
                            # NOTE: Making an assumption that we are only returning results from the
                            # first valid third party service
                            break

            # if we had an error with both service requests, but no error has been set, do it now
            # this handles cases like wrong API keys, offline services, etc.
            if not geo_proxy_response.status == "OK" and geo_proxy_response.error is None:
                geo_proxy_response.set_error(
                    "Error in third-party API requests", "UNKNOWN_ERROR")

        except Exception as e:
            geo_proxy_response.set_error(
                "Caught general exception in server: {}".format(e),
                "UNKNOWN_ERROR")

        # Ensure that a response is always sent so the socket doesn't bind
        self.write(geo_proxy_response.to_json())
        self.logger.info(
            "Response completed in {:0.2f} seconds".format(time.time() -
                                                           start_time))