Requests lib changing characters to URL-encoded representation - python

I am trying to send a get request to an api that includes timestamps. The URL is getting changed and instead of : %253A is inserted and I get a 500 error code.
url = 'https://www.fleetTrackingSimplicity.com/REST6/api/vehiclehistory/2'
start = '2020-12-01T00:00:00Z'
end = '2020-12-02T00:00:00Z'
param = {'startdate': start, 'enddate': end, 'count':'500'}
r_auth = str(a_json['TransactionId'])
headers2 = dict (Authorization = r_auth, Accept = 'application/json')
r = requests.get(url, headers = headers2, params=param)
When I print r.url I get https://www.fleettrackingsimplicity.com/REST6/api/vehiclehistory/2?startdate=2020-12-01T00%253A00%253A00Z&enddate=2020-12-02T00%253A00%253A00Z&count=500

Related

Api call using python and token_auth

"""
#Collects basic metrics from Matomo installation and returns a pandas dataframe
"""
token = os.getenv("token")
# Build url string
base_url = 'https://matomo.___.com/index.php?module=API'
site_num = '&idSite=1'
return_format = '&format=json'
period = '&period=day'
date_range = '&date=last30'
method = '&method=VisitsSummary.get'
token_string = "&token_auth=" + token
my_url = base_url + site_num + return_format + period + date_range + method + token_string
# send request for report
r = requests.get(my_url)
# parse and tidy collected data
data = pd.DataFrame(r.json()).T
data = data.reset_index()
data.columns = [
"date",
"uniq_visitors",
"users",
"visits",
"actions",
"visits_converted",
"bounces",
"sum_visit_length",
"max_actions",
"bounce_rate",
"actions_per_visit",
"avg_time_on_site",
]
return data
I am trying to get data from the matomo API using an auth_token and parameters by using above code but i am not able to access it and my url is not taking token code any one has idea how i can solve this
Given that you are using the request library, passing parameters and headers can be done using the following params in your get call:
r = requests.get(my_url, params=payload)
In the same way, an auth token is usually passed within headers:
r = requests.get(my_url, params=payload, headers=headers)
Using this format you can simply create a headers object which contains your token_auth and directly pass your parameters in a payload object:
headers = {'token_auth': token}
payload = {'module':'API', 'idSite':1, 'format':'json', 'period':'day', 'date':'last30', 'method':'VisitsSummary.get'}
Since you are now passing your parameters in you get request, there is no need to add them to the end of your url. Thus, your url should stay as https://matomo.___.com/index.php. These can then be used within your params and headers respectively. Please note that this assumes that the matomo API places the token_auth in its headers such as most APIs do. If this is not the case you could pass it directly within the params payload.
Here is a global overview:
token = os.getenv("token")
# Get url, headers and params
my_url = 'https://matomo.___.com/index.php'
payload = {'module':'API', 'idSite':1, 'format':'json', 'period':'day', 'date':'last30', 'method':'VisitsSummary.get'}
headers = {'token_auth': token}
# send request for report
r = requests.get(my_url, params=payload, headers=headers)
Note this answers your question specifically regarding the API call and not the processing after.

Requests: Error sending payload in python post request

The code behaving strangely that I am unable to understand what's going on..
The code that works fine:
link = "https://api.luminati.io/dca/trigger_immediate?collector=XXXxxxXXXxxxXXXX"
head = {"Authorization": "Bearer xxXXxxXXxx" ,"Content-Type": "application/json"}
data = '{"url":"https://www.practo.com/pune/doctor/XXXXXXxXXXXX"}'
res = requests.post(link, headers = head, data = data)
print("Status: "+str(res.status_code), "Message: "+res.text)
Output:
Status: 202 Message: {"response_id":"z7627t1617552745375r14623bt37oo"}
But I want to load "url":"https://www.practo.com/pune/doctor/XXXXXXxXXXXX" this thing dynamically.
url = "https://www.practo.com/pune/doctor/XXXXXXxXXXXX"
link = "https://api.luminati.io/dca/trigger_immediate?collector=XXXxxxXXXxxxXXXX"
head = {"Authorization": "Bearer xxXXxxXXxx" ,"Content-Type": "application/json"}
data = {"url":url}
res = requests.post(link, headers = head, data = data)
print("Status: "+str(res.status_code), "Message: "+res.text)
Output:
Status: 500 Message: 'Unexpected token u in JSON at position 7'
To load data dynamically try using %s string feature, like that:
url = "https://www.practo.com/pune/doctor/XXXXXXxXXXXX"
data = '{"url":"%s"}' % url
or you can convert dictionary entirely to str, like:
import json
data = {"url":link}
res = requests.post(link, headers=head, data=json.dumps(data))
by the way, you can pass body not like data, but like json, here's documents:
:param json: (optional) json data to send in the body of the :class:Request. So your request will look like:
data = {"url":link}
res = requests.post(link, headers=head, json=data)
any_dynamic_variable='XXXXXXxXXXXX'#You can make your websit or part of the url to be dynamic
url = f'https://www.practo.com/pune/doctor/{any_dynamic}'
headers = {"Authorization": "Bearer xxXXxxXXxx" ,"Content-Type": "application/json"}
payload={
'your_key':'your_value',
'currancy':'CA',#<==== This is an example
}
r = requests.post(url,headers=headres,data=payload}
print(r.status_code)#check your status to be able to find the error if you have any
print(r.text)

How to preserve the Ascii encoding type with the POST request in Python?

How do I send the ASCII encoded text via POST request in Python? The length of true_input I received via the POST is always different from the length I sent.
def insert_true_input(level, iteration, true_input):
url = master_url + "/insert_true_input?"
data = {'level': level, 'iteration': iteration, 'true_input': true_input}
headers = {'Content-Type': 'text/plain'}
res = requests.post(url, params=data, headers=headers).text
return res
The sample true_input that I want to send is directly from numpy.ndarray.tostring() and looks like
'\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00#\x00\x00\x00\x00\x00\x00\x08#\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x007#\x00\x00\x00\x00\x00\xc0^#\x00\x00\x00\x00\x00\xc0^#\x00\x00\x00\x00\x00\xc0^#\x00\x00\x00\x00\x00\x00(#\x00\x00\x00\x00\x00\x00?#'
As explained in the comments, the null characters \x00 are not sendable in raw text. You have to encode them one way or another (URL encoded, Base64, json, etc.). But then the other side that will receive the request must be adapted to decode them accordingly.
Actually requests will use URL encoding automatically for the parameters passed in the query string, but I suspect that your java code is not able to decode them properly.
Please post your Java code for the receiving side to see what we can do.
Suggestions on python side, using base64:
import base64
def insert_true_input(level, iteration, true_input):
url = master_url + "/insert_true_input?"
data = {'level': level, 'iteration': iteration, 'true_input': base64.b64encode(true_input)}
res = requests.post(url, params=data, headers=headers).text
return res
Using json (requests will do the work for you if you use the json parameter to .post()):
def insert_true_input(level, iteration, true_input):
url = master_url + "/insert_true_input?"
data = {'level': level, 'iteration': iteration, 'true_input': true_input}
res = requests.post(url, json=data, headers=headers).text
return res
You have to encode your string using str.encode('ascii'):
def insert_true_input(level, iteration, true_input):
url = master_url + "/insert_true_input?"
data = {'level': level, 'iteration': iteration, 'true_input': true_input.encode('ascii')}
headers = {'Content-Type': 'text/plain'}
res = requests.post(url, params=data, headers=headers).text
return res

Problems with sending string array/list through query string

I'm trying to send a string array to the bing translate api, which I have received and encoded as UTF-8.
However, when I make the call with the variable the service spits out an error:
"There was an error deserializing the object of type System.String[]. Encountered unexpected character 'ï'."
If I manually add the string array as a string not within a variable, it works. I'm using the Requests module, so I'm thinking it's encoding the url... I have no idea.
class getLanguages(apiFunctions):
def GET(self):
#get the access token
data = self.accessToken()
token = data['access_token']
codes = self.getCodes(token)
languageNames = self.getLanguageNames(token,codes)
codesList = ast.literal_eval(codes)
return languageNames + codes
def getCodes(self,token):
url = 'http://api.microsofttranslator.com/V2/Ajax.svc/GetLanguagesForTranslate'
auth_header = {'Authorization': 'Bearer ' + token}
r = requests.get(url, headers=auth_header)
return r.text.encode('utf-8')
def getLanguageNames(self,token,codes):
url = 'http://api.microsofttranslator.com/V2/Ajax.svc/GetLanguageNames'
#this is where I add the language codes string to the query
payload = {'locale': 'en', 'languageCodes': codes}
auth_header = {'Authorization': 'Bearer ' + token}
r = requests.post(url, params=payload, headers=auth_header)
return r.text.encode('utf-8')
And this is the string:
["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","tlh-Qaak","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]

oauth1, rsa-sha1, header params

I have been using requests-oauthlib, which do have rsa-sha1 signature algorithm, but there can't seem to be a way to add extra params to the authorization header, and if i do modify the header manually before making the request i get
"The request contains an incomplete or invalid oauth_signature."
because it had already created the oauth_signature when i have added the new oauth_body_hash to the authorization header.
i have pasted the code, the first call using oauth passes correctly, but the second one is giving the error.
any possible way to workaround this ? another library that has both options to add extra params and provide rsa-sha1 signature ?
oauth = OAuth1(
consumer_key,
signature_method='RSA-SHA1',
signature_type='auth_header',
rsa_key=key,
callback_uri=callback_uri
)
oauth.client.realm = 'eWallet'
r = requests.post(url=request_token_url, auth=oauth)
credentials = parse_qs(r.content)
# end of request
# post shopingcart
root = ET.fromstring(shopping_cart_xml)
root.find('OAuthToken').text = credentials['oauth_token'][0]
xml = ET.tostring(root, encoding="us-ascii", method="xml")
sha1 = hashlib.sha1()
sha1.update(xml)
oauth_body_hash = sha1.digest()
oauth_body_hash = base64.b64encode(oauth_body_hash)
oauth.client.oauth_body_hash = oauth_body_hash
req = Request('POST', shopping_cart_url, data=xml, auth=oauth)
prepped = req.prepare()
auth_header = prepped.headers['Authorization'] + ', oauth_body_hash="%s"' % (oauth_body_hash)
headers = {'Content-Type': 'application/xml', 'Authorization': auth_header}
r = requests.post(url=shopping_cart_url, headers=headers, data=xml)

Categories

Resources