abdullahselek / HerePy

A library that provides a Python interface to the HERE location APIs.
https://herepy.abdullahselek.com/
MIT License
83 stars 35 forks source link

urlencode seems to be breaking some API calls #30

Closed dkori closed 4 years ago

dkori commented 4 years ago

I was not getting a response with the FleetTelematicsAPI function, so I tried to manually recreate it. It appears that my API call was breaking because urlencode was replacing semicolons and commas in the api call. base_url = 'https://wse.ls.hereapi.com/2/findsequence.json' data_test = {'apiKey':'key', 'start':'Start;43.422,-75.9201', 'destination1': 'dest1;43.46929,-75.92747', 'destination2': 'dest2;43.45939,-75.89347'} url = herepy.Utils.build_url(base_url,extra_params=data_test) url

Will return: 'https://wse.ls.hereapi.com/2/findsequence.json?apiKey=key&start=Start%3B43.422%2C-75.9201&destination1=dest1%3B43.46929%2C-75.92747&destination2=dest2%3B43.45939%2C-75.89347'

dkori commented 4 years ago

I think you can resolve this by wrapping destination_param in urllib.parse.quote to specify safe characters. You also need to pass the "safe=';,'" argument to urlencode in the build_url utility.

for destination_param in intermediate_destinations: count += 1 data[str.format('destination{0}', count)] = urllib.parse.quote(destination_param,safe=';,')

abdullahselek commented 4 years ago

Hi @dkori thanks for raising a possible issue. I guess you tried find_sequence function, I just tried and it works as expected. I can also see that you have some missing parameter which is required modes: List[RouteMode]. If you can give me some more details I could help you.

dkori commented 4 years ago

Yes that's correct, I was using the find_sequence function. When I enter the following, I get an error:

start = 'Start;43.422,-75.9201'

end = 'End;43.422,-75.9201'

intermediate_destinations = ['dest1;43.46929,-75.92747','dest2;43.45939,-75.89347']

departure = '2020-08-30T17:00:00+02'

mode = ['fastest;pedestrian']

response = herepy.FleetTelematicsApi()

test = response.find_sequence(start = start,

                             departure = departure,

                             intermediate_destinations = intermediate_destinations,

                             end = end,

                            modes = mode)

However, using the following, it returns a url that results in a correct API response (when I swap in the key correctly):

base_url = 'https://wse.ls.hereapi.com/2/findsequence.json'

data_test = {'apiKey':'key',

            'start':'Start;43.422,-75.9201',

            'destination1': 'dest1;43.46929,-75.92747',

            'destination2': 'dest2;43.45939,-75.89347',

            'end':'End;43.422,-75.9201',

            'mode':'fastest;pedestrian'}

url = base_url+'?'+urlencode(data_test,safe=";,")

url
abdullahselek commented 4 years ago

Below you can find a working code snippet

import herepy

fleetTelematicsApi = herepy.FleetTelematicsApi(api_key='api_key')

start = str.format('{0};{1},{2}', 'WiesbadenCentralStation', 50.0715, 8.2434)
intermediate_destinations = [str.format('{0};{1},{2}', 'FranfurtCentralStation', 50.1073, 8.6647),
    str.format('{0};{1},{2}', 'DarmstadtCentralStation', 49.8728, 8.6326),
    str.format('{0};{1},{2}', 'FrankfurtAirport', 50.0505, 8.5698)]
end = str.format('{0};{1},{2}', 'MainzCentralStation', 50.0021, 8.259)
modes = [herepy.RouteMode.fastest, herepy.RouteMode.car, herepy.RouteMode.traffic_enabled]
response = fleetTelematicsApi.find_sequence(start=start,
        departure='2020-08-02T09:30:00%2b01:00',
        intermediate_destinations=intermediate_destinations,
        end=end,
        modes=modes)
dkori commented 4 years ago

I get the same error when running your working snippet:

---------------------------------------------------------------------------
HEREError                                 Traceback (most recent call last)
<ipython-input-123-091953ea1f7b> in <module>
     10         intermediate_destinations=intermediate_destinations,
     11         end=end,
---> 12         modes=modes)

~/anaconda3/lib/python3.7/site-packages/herepy/fleet_telematics_api.py in find_sequence(self, start, departure, intermediate_destinations, end, modes)
    135                                                       end=end,
    136                                                       modes=modes)
--> 137         response = self.__get(self._base_url + 'findsequence.json', data, WaypointSequenceResponse)
    138         return response
    139 

~/anaconda3/lib/python3.7/site-packages/herepy/fleet_telematics_api.py in __get(self, base_url, data, response_cls)
    103             return response_cls.new_from_jsondict(json_data)
    104         else:
--> 105             raise error_from_fleet_telematics_service_error(json_data)
    106 
    107 

HEREError: Error occured on __get

These are the versions of packages I have installed:

herepy_version:  3.0.1
requests_version:  2.24.0

Any ideas?

abdullahselek commented 4 years ago

I hope you set your API key for the request, sorry but I don't know what exactly you are trying so it is hard for me to help you.

dkori commented 4 years ago

Sorry yes, to clarify, I ran the code snippet you posted exactly as you posted it except I replaced 'api_key' with my api key. I know that my api_key is working because I was able to successfully run API calls with it manually outside of Herepy.

Do you have any advice for debugging? I still think part of the issue is the encoding of the url using urlib, but I am not sure why the code snippet you posted works on your machine but not mine.

I found a work-around for my purposes, but I can keep the issue open in case others run into it as well.

abdullahselek commented 4 years ago

Yes that's correct, I was using the find_sequence function. When I enter the following, I get an error:

start = 'Start;43.422,-75.9201'

end = 'End;43.422,-75.9201'

intermediate_destinations = ['dest1;43.46929,-75.92747','dest2;43.45939,-75.89347']

departure = '2020-08-30T17:00:00+02'

mode = ['fastest;pedestrian']

response = herepy.FleetTelematicsApi()

test = response.find_sequence(start = start,

                             departure = departure,

                             intermediate_destinations = intermediate_destinations,

                             end = end,

                            modes = mode)

However, using the following, it returns a url that results in a correct API response (when I swap in the key correctly):

base_url = 'https://wse.ls.hereapi.com/2/findsequence.json'

data_test = {'apiKey':'key',

            'start':'Start;43.422,-75.9201',

            'destination1': 'dest1;43.46929,-75.92747',

            'destination2': 'dest2;43.45939,-75.89347',

            'end':'End;43.422,-75.9201',

            'mode':'fastest;pedestrian'}

url = base_url+'?'+urlencode(data_test,safe=";,")

url

@dkori I checked your parameters today one more time and I realised you were passing wrong parameters for modes. herepy needs a list of RouteMode enum not strings.

def find_sequence(
        self,
        start: str,
        departure: str,
        intermediate_destinations: List[str],
        end: str,
        modes: List[RouteMode],
    ) -> Optional[WaypointSequenceResponse]:

and your mode parameter

mode = ['fastest;pedestrian']

Please try again and let me know.

abdullahselek commented 4 years ago

Closing because of inactivity.