Why does Bearer not work in requests authorization header? - python

I'm having a problem sending an authorization token with Bearer to NEST API via python requests:
curl https://developer-api.nest.com -H "Authorization: Bearer c.123"
-H "Content-Type: application/json"
works fine, however:
nest_url = "https://developer-api.nest.com"
headers = {'Authorization': str('Bearer ' + token), 'Content-type': 'application/json'}
print(headers)
nest_data_req = requests.get(nest_url, headers=headers)
which prints as:
{'Content-type': 'application/json', 'Authorization': 'Bearer c.123'}
fails with a 401 unauthorized, as far as I can tell they are trying to make the same request so why does curl work (and postman for that matter) and python requests fail?
The following image shows the same working in postman:
Update:
So this code works 1 in 10 times (the other 9+ give me 401 unauthorized):
url = "https://developer-api.nest.com/"
auth_t = token.encode("ascii", "ignore")
headers = {
'authorization': "Bearer " + auth_t,
'content-type': "application/json",
'cache-control': "no-cache",
}
response = requests.request("GET", url, headers=headers)
print(response.text)
if I press submit in postman it works everytime without fail.

Turns this is a result of nest's API redirecting so you could consider this either a bug - as headers are removed from the redirected request, and headers should be on the session. Or a 'feature' as they were trying to resolve a CVE.
So here is a prototyped way to handle this:
def get_nest_data(token):
url = "https://developer-api.nest.com/"
auth_t = token.encode("ascii", "ignore")
headers = {
'authorization': "Bearer " + auth_t,
'content-type': "application/json",
}
try:
init_res = requests.get('https://developer-api.nest.com', headers=headers, allow_redirects=False)
if init_res.status_code == 307:
api_response = requests.get(init_res.headers['Location'], headers=headers, allow_redirects=False)
if api_response.status_code == 200:
return api_response.json()
elif init_res.status_code == 200:
return init_res.json()
except Exception as ce:
print(ce)

Related

Failed to read the request form. Missing content-type boundary after convert request from curl or postman during send zip file

I would like to send a zip file using Python Requests. How to correct my code to send the zip file correctly?
My Curl request working fine and returns 200
curl -X 'POST' \
'https://xxx/bulk' \
-H 'accept: application/json;odata.metadata=minimal;odata.streaming=true'
-H 'Authorization: Basic xxx'
-H 'Content-Type: multipart/form-data'
-F 'File=#/home/dominik/ok/batch.zip;type=application/x-zip-compressed'
My Postman request returns 200. But the Python code from the Postman generator doesn't work.
Python code
headers = {
'accept': 'application/json;odata.metadata=minimal;odata.streaming=true',
'Content-Type': 'multipart/form-data',
'Authorization' : 'Basic xxx'}
def send_zip(zip_path, url, headers):
start_time = time.perf_counter()
zip_to_send = {'file': ('batch.zip', open(zip_path, 'rb'), 'application/x-zip-compressed')}
response = requests.request('POST', url, headers=headers, files=zip_to_send)
print(response.text, response.status_code)
end_time = time.perf_counter()
total_time = end_time - start_time
print(f'Total time to send zip: {total_time}')
my code returns
Failed to read the request form. Missing content-type boundary
I know about curlconverter but it returns the code with the file error
headers = {'accept': 'application/json;odata.metadata=minimal;odata.streaming=true',
'Authorization': 'Basic xxx,
# requests won't add a boundary if this header is set when you pass files=
# 'Content-Type': 'multipart/form-data',
}
fils = {'File': open('/hoome/ok/batch.zip;type=application/x-zip-compressed', 'rb'),}
response = requests.post('https://xxx/bulk', headers=headers, files=files, )

Python post request throwing 400 'Bad Request' error with requests library but works with cURL

I have a script that calls a POST endpoint but getting a 400 error. Meanwhile, the corresponding cURL request is successful.
First, here is the cURL:
curl -X 'POST' \
'http://localhost:8080/api/predict?Key=123testkey' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=#156ac81cde4b3f22faa4055b53867f38.jpg;type=image/jpeg'
And translated to requests:
import requests
url = 'http://localhost:8080/api/predict?Key=123testkey'
headers = {
'accept': 'application/json',
'Content-Type': 'multipart/form-data',
}
params = {'Key' : '123testkey'}
files = {'image': open('156ac81cde4b3f22faa4055b53867f38.jpg', 'rb')}
response = requests.post(url, files=files, params=params, headers=headers)
Have also tried using a URL that does not include the key, since the key is already specified in params:
import requests
url = 'http://localhost:8080/api/predict'
headers = {
'accept': 'application/json',
'Content-Type': 'multipart/form-data',
}
params = {'Key' : '123testkey'}
files = {'image': open('156ac81cde4b3f22faa4055b53867f38.jpg', 'rb')}
response = requests.post(url, files=files, params=params, headers=headers)
I thought this should be simple but I consistently get the 400 error with requests no matter what I try. Any suggestions?
Edit: have also tried 'image/jpeg' instead of 'image' to no avail.
Edit: replacing the "image" key with "file" unfortunately didn't work either
Edit: It works in postman desktop just fine, and generates the following code. However, this code also throws an error.
The generated code from postman:
import requests
url = "http://localhost:8080/api/predict?Key=123test"
payload={}
files=[
('file',('images19.jpg',open('156ac81cde4b3f22faa4055b53867f38.jpg','rb'),'image/jpeg'))
]
headers = {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.text)
And the error from the previously generated code from postman:
{"detail":"There was an error parsing the body"}
Any help figuring out what is going on would be much appreciated!
Your issue is in the variable files you need to add with the key 'file' instead of 'image' that's the difference between your curl and your python code, also remove the header because when you pass the file parameter the request set the proper header for send files. for example:
import requests
url = 'http://localhost:8080/api/predict?Key=123testkey'
params = {'Key' : '123testkey'}
files = {'file': open('156ac81cde4b3f22faa4055b53867f38.jpg', 'rb')}
response = requests.post(url, files=files, params=params)

Empty body error on post request in python script

I'm trying to make a post request to an API endpoint with python and requests.
The endpoint requires a token. I get the token from the endpoint just fine.
When making a post request to the second endpoint Validation Error stating that body is empty.
import requests
url = "https://authz.dinero.dk/dineroapi/oauth/token"
payload = 'grant_type=password&username=****&password=****'
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ****'
}
response = requests.request("POST", url, headers=headers, data = payload)
r =response.json()
token = r['access_token']
url = "https://api.dinero.dk/v1/257403/contacts"
payload = {}
payload["Name"] = "Test Name"
payload["CountryKey"] = "DK"
payload["IsPerson"] = "true"
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
}
response = requests.post(url, headers=headers, data = payload)
print(response.text)
This is the error I get:
{"code":42,"message":"Validation Error","validationErrors":{"Body":"The body was empty"},"languageSpecificMessages":[{"property":"message","message":"Der er fejl i de angivne data"},{"property":"Body","message":"The body was empty"}],"errorMessageList":[{"Code":"Body","Message":"The body was empty"}]}
Here is the same code taken from postman. It works fine.
import requests
url = "https://api.dinero.dk/v1/257403/contacts"
payload = "{\r\n \"Name\": \"Test Name\",\r\n \"CountryKey\": \"DK\",\r\n \"IsPerson\": true\r\n}"
print(payload)
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ****'
}
response = requests.request("POST", url, headers=headers, data = payload)
print(response.text.encode('utf8'))
I hope someone can explain why my code isn't working.
Requests has a json= param you could use:
response = requests.post(url, headers=headers, json=payload)
Docs here.
In your second call, you want to json dump the payload:
import json
response = requests.post(url, headers=headers, data=json.dumps(payload))
Postman has already serialised the payload as a json formatted string. You can do the same with json.dumps().

Error posting comments using Facebook Graph API

My aim is to post a comment to a particular post id using Facebook graph API.
This is the code snippet for the same:
url = 'https://graph.facebook.com/v2.11/<post_id>/comments'
parameters = {'access_token': <FACEBOOK_ACCESS_TOKEN>, 'message': 'test comment'}
headers = {"content-type": "application/json"}
parameters = json.dumps(parameters)
response = requests.post(url, data=parameters, headers=headers, timeout=10)
I am calling this API inside my DJANGO POST API.
For Some Reason, Calling the Facebook API through this code doesnt work. The API call gets timeout after 10 seconds.
If I call the Facebook API through Postman / YARC , the comment gets posted successfully.
Can any one tell me where I am going wrong?
Python Requests example:
import requests
url = "https://graph.facebook.com/v2.11/yourPostId/comments"
querystring = {"access_token":"yourtoken"}
payload = "message=test%20comment"
headers = {
'content-type': "application/x-www-form-urlencoded",
'cache-control': "no-cache"
}
response = requests.request("POST", url, data=payload, headers=headers, params=querystring)
print(response.text)
Python http.client example:
import http.client
conn = http.client.HTTPSConnection("graph.facebook.com")
payload = "message=test%20comment"
headers = {
'content-type': "application/x-www-form-urlencoded",
'cache-control': "no-cache"
}
conn.request("POST", "/v2.11/yourPostId/comments?access_token=yourtoken", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

Error while accessing API v2 from thetvdb.com [Python requests. Error 403 ]

I am trying to access the API v2 from thetvdb.com. Unfortunately I always get the 403 error.
Here is what I have:
#!/usr/bin/python3
import requests
url = "https://api.thetvdb.com/login"
headers = {'content-type': 'application/json'}
payload = {"apikey":"123","username":"secretusername","userkey":"123"}
post = requests.post(url, data = payload, headers = headers)
print(post.status_code, post.reason)
According to the API documentation I have to authenticate in order to get a token. But I just get 403 Forbidden.
Now I tried it using curl:
curl -X POST --header 'Content-Type: application/json' --header 'Accept:
application/json' -d
{"apikey":"123","username":"secretusername","userkey":"123"}'
'https://api.thetvdb.com/login'
And this worked perfectly. Can anyone explain me what I am missing? This is driving me insane.
I also tried it with
post = requests.post(url, data = json.dumps(payload), headers = headers)
Same error.
You have to explicitly convert the payload to json string and pass asdata . It looks like you have done that also you may try setting the user-agent as curl/7.47.1
headers = {'content-type': 'application/json', 'User-Agent': 'curl/7.47.1'}
post = requests.post(url, data = json.dumps(payload), headers = headers)
The program will look like
#!/usr/bin/python3
import requests
import json
url = "https://api.thetvdb.com/login"
headers = {'content-type': 'application/json', 'User-Agent': 'curl/7.47.1'}
payload = {"apikey":"123","username":"secretusername","userkey":"123"}
post = requests.post(url, data = json.dumps(payload), headers = headers)
print(post.status_code, post.reason)
I think you need to pass Accept headers in the python requests. Something like this:
header = {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
"Accept-Encoding": "gzip, deflate, sdch, br",
"Accept-Language": "en-US,en;q=0.8",
"User-Agent": "some user-agent",
}
url = 'http://169.254.169.254/latest/meta-data/iam/'
payload = {}
headers = {'content-type': 'application/json', 'User-Agent': 'curl/7.47.1'}
#headers = {'content-type': 'application/json'}
response = requests.post(url, headers=headers, data=payload,
verify='/installed/aws/usr/lib/python2.7/site-
packages/certifi/cacert.pem', timeout=5)
instance_profile_role_name = response.text
print response.text`

Categories