Python Requests Explicitly Setting Headers Causes 400 Response - python

I am attempting to make a POST to a web server. I have data that I want to post in the body and headers (taken directly from Chrome). Without going into too many details, when I explicitly set headers, I get a 400 response code.
# Explicitly set headers causes 400 response
req = requests.post(url, auth_form, headers=authenticate)
print(req.status_code)
But the following returns a 200 response code:
# Setting data as my form to post and headers as json
# Returns a 200 response code
req = requests.post(url, auth_form, authenticate)
print(req.status_code)
I am attempting to simulate a login through code. Even when I receive the 200 response I do not successfully login. I suspect this is because I am not properly setting the headers, but I am unsure.
I am actually able to remove the headers entirely (as either headers= or json) and still receive a 200 response code. I believe this reinforces the idea that the headers are not being set properly.
# Removing headers entirely
# Returns a 200 response code
req = requests.post(url, auth_form)
print(req.status_code)
I am not sure if additional details (such as what some of the headers are) will be necessary. If so, I will provide as much of that information as I can.
Edit: Headers, as requested:
authenticate = {}
authenticate["Accept"] = accept
authenticate["Accept-Encoding"] = "gzip, deflate, br"
authenticate["Accept-Language"] = "en-US,en;q=0.8"
authenticate["Cache-Control"] = "max-age=0"
authenticate["Connection"] = "keep-alive"
authenticate["Host"] = dns + ":" + str(port)
authenticate["Origin"] = "http://" + dns + ":" + str(port)
authenticate["Referer"] = "http://" + dns + ":" + str(port) + "/eproc/"
authenticate["Upgrade-Insecure-Requests"] = upgrade_insecure
authenticate["Cookie"] = "ID=" + self.session_id
authenticate["User-Agent"] = user_agent
auth_form = {}
auth_form["username"] = username
auth_form["password"] = password

Related

How change the encoding in POST method in CaseInsensitiveDict()?

First thank you for your time. I'm trying to do an insert using a Rest-API POST, I'm working with Python. Among my messages I have special characters that I want to keep in the destination, which by the way returns an error for them since by default the messages are in UTF-8, but I want them in "ISO-8859-1".
For this I have created the line: headers["Charset"] = "ISO-8859-1" . Python does not give me an error but I continue with the same problem.
The error is:
400 Client Error: Bad Request for url: https://api.example.com/
Here is my code:
import requests
from requests.structures import CaseInsensitiveDict
url = 'https://api.example.com/'
headers = CaseInsensitiveDict()
headers["Accept"] = "application/json"
headers["Authorization"] = "Bearer "
headers["Content-Type"] = "application/json"
headers["Charset"] = "ISO-8859-1"
collet_x = df_spark.collect()
for row in collet_x:
#insert
resp = requests.post(url, headers=headers, data=row['JSON'])
v_respuesta = resp.text
print(resp.status_code)
print(v_respuesta)
How else can I change the encoding?
From already thank you very much.
Regards

Getting Response Code as 500 when hitting Rest API in Python

I am using requests.get() to invoke the REST api. When i hardcode the URL it is working fine but if i append the account name with URL getting the response code as 500. Please help.
header = {'Authorization': token_type + " " + token, 'Content-Type': 'application/json'}
account_name="test_account"
uri = "https://my_instance.salesforce.com/services/apexrest/account/entitlement?AccountName="+account_name
user_create_res = requests.get(uri, headers=header)
but same code is working when i give,
header = {'Authorization': token_type + " " + token, 'Content-Type': 'application/json'}
uri = "https://my_instance.salesforce.com/services/apexrest/account/entitlement?AccountName=test_account"
user_create_res = requests.get(uri, headers=header)
Try printing the account_name variable using
print(account_name)
Make sure the text logged in the console is the same as the name you tried hard coding.
Though it could also be that the account_name variable is not a String.
I can not say for sure if I don't get more info like where you define the account_name variable.

POST request using urllib2 doesn't correctly send data (401 error)

I am trying to make a POST request in Python 2, using urllib2. My code is currently as follows;
url = 'http://' + server_url + '/playlists/upload?'
data = urllib.urlencode(OrderedDict([("sectionID", section_id), ("path", current_playlist), ("X-Plex-Token", plex_token)]))
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
d = response.read()
print(d)
'url' and 'data' return correctly formatted with the variables, I know this because I can copy their output into Postman for checking and the POST works fine (see example url below)
http://192.168.1.96:32400/playlists/upload?sectionID=11&path=D%3A%5CMedia%5CPPP%5Ctmp%5Cplex%5CAmbient.m3u&X-Plex-Token=XXXXXXXXX
When I run my Python code I get a 401 error returned, presumably meaning the X-Plex-Token parameter was not correctly sent, hence I am not allowed access.
Can anyone tell me where I'm going wrong? Help is greatly appreciated.
Have you tried removing the question mark and not using OrderedDict (no idea why you would need that) ?
url = 'http://' + server_url + '/playlists/upload'
data = urllib.urlencode({"sectionID":section_id), "path":current_playlist,"X-Plex-Token":plex_token})
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
d = response.read()
print(d)
Of course you should be using requests instead anyway:
import requests
r = requests.post('http://{}/playlists/upload'.format(server_url), data = {"sectionID":section_id), "path":current_playlist,"X-Plex-Token":plex_token})
print r.url
print r.text
print r.json
I've ended up switching to Python 3, as I didn't realise that the requests module was included by default. Still no idea why the above wasn't working, but maybe something to do with the lack of headers
headers = {'cache-control': "no-cache"}
edit:
This is what I'm using now, as mentioned above I probably don't need OrderedDict.
import requests
url = 'http://' + server_url + '/playlists/upload'
headers = {'cache-control': "no-cache"}
querystring = urllib.parse.urlencode(OrderedDict([("sectionID", section_id), ("path", current_playlist), ("X-Plex-Token", plex_token)]))
response = requests.request("POST", url, data = "", headers = headers, params = querystring)
print(response.text)

Basic Authentication returns 401 Client Error but works in postman

I have gone through number of similar posts related to firing GET requests with Basic Auth (eg: Python, HTTPS GET with basic authentication), still can't figure out the problem. I keep getting the error requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url
With the same credentials, headers tried the same in postman it works as expected. Verified that base64encoded value for the api_key, password is exactly same as the value used in postman, so I don't think its encoding or resource access permission problem.
python -V
Python 3.6.4 :: Anaconda, Inc.
Approach 1
api_key = 'some_api_key'
password = 'some_password'
headers = {'accept': 'application/json'}
url = 'https://test.access.com/this/url'
api_key_password = "%s:%s" % (api_key, password)
b64_encoded = b64encode(bytes(api_key_password, 'utf-8')).decode("ascii")
headers['authorization'] = 'Basic %s' % b64_encoded
response = requests.get(url,
headers=headers)
if (response.ok):
json_data = json.loads(response.content)
print (json_data)
else:
print (response)
response.raise_for_status()
Approach 2
api_key = 'some_api_key'
password = 'some_password'
url = 'https://test.access.com/this/url'
headers = {
'accept': 'application/json',
}
response = requests.get(url, headers=headers, auth=(api_key, password))
print (response.ok)
if (response.ok):
json_data = json.loads(response.content)
print (json_data)
else:
print (response)
response.raise_for_status()
Can you please provide some pointers?
I had a similar issue (although in .NET Framework).
In my case the reason was that I was using the url without a forward slash in the end and the API apparently does not support that.
So https://test.access.com/this/url
Throws 401 error Unauthorized
but
https://test.access.com/this/url/
Returns 200 OK.
Older post but I had a similar issue. Postman will cache your JSESSIONID. Be sure you are clearing out that cookie while testing. If you are hitting an API that requires a login API call to establish a session before you can make subsequent API calls, this Postman behavior can produce a false sense of security.
In this situation with Python requests, it can be handled with code similar to what I've provided below:
import requests,json
loginAPI = "https://myapi.myco.comv/someuri/someuri/users/login"
someHTTPGetAPI = "https://myapi.myco.com/someuri/someuri/someservice"
username = "myuser"
password = "mypass"
headers = {
"Content-Type": "application/json",
"login": username,
"password": password
}
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
verify=False
session = requests.Session()
sessionResponse = session.get(url=loginURL,headers=headers, verify=verify)
if sessionResponse.status_code == 200:
getResponse = session.get(url=someHTTPGetAPI)
if getResponse.status_code == 200:
responseJSON = agentStatus.json()

Exception Value: HTTP Error 400: Bad Request after a Python/urllib2 request to PayPal Sandbox Site

I'm trying to integrate PayPal REST API in my website. As a first step, I'm trying to translate cURL commands into Python and I'm getting an Exception Value: HTTP Error 400.
The code I'm using (is based on https://stackoverflow.com/a/2003832/2675537):
def basic_authorization(user, password):
s = user + ":" + password
return "Basic " + s.encode("base64").rstrip()
req = urllib2.Request("https://api.sandbox.paypal.com/v1/oauth2/token",
headers = {
"Authorization": basic_authorization("EBWKjlELKMYqRNQ6sYvFo64FtaRLRR5BdHEESmha49TM", "EO422dn3gQLgDbuwqTjzrFgFtaRLRR5BdHEESmha49TM"),
"Accept": "application/json",
"Accept": "*/*",
"User-Agent": "my-python-app/1",
},
data = '{"message":{"body":' + 'grant_type=client_credentials' + '}}' )
f = urllib2.urlopen(req)
return HttpResponse(f)
which is the equivalent (I guess) to:
curl https://api.sandbox.paypal.com/v1/oauth2/token \
-H "Accept: application/json" \
-u "EBWKjlELKMYqRNQ6sYvFo64FtaRLRR5BdHEESmha49TM:EO422dn3gQLgDbuwqTjzrFgFtaRLRR5BdHEESmha49TM" \
-d "grant_type=client_credentials"
And the traceback is here: (Edit: Broken Link)
According to PayPal I should get a response like this:
{"scope":"https://api.paypal.com/v1/payments/.* https://api.paypal.com/v1/vault/credit-card https://api.paypal.com/v1/vault/credit-card/.* https://api.paypal.com/v1/developer/.*","access_token":"OABI8rm75u.5EIuK7.JrI2sLhnv3rhDgLElKAwTfyys","token_type":"Bearer","app_id":"APP-2EJ531395M785864S","expires_in":28800}
Is there an error in my code? Is there a better way to do it?
First of all, I would suggest you not to post your keys in clear text in your code examples.
The error your getting "HTTP Error 400: Bad Request", is due to a badly formed request.
From the docs the format for a request is:
urllib2.Request(url[, data][, headers][, origin_req_host][, unverifiable])
data may be a string specifying additional data to send to the server,
or None if no such data is needed.
headers should be a dictionary, and will be treated as if add_header()
was called with each key and value as arguments.
So your data field is passing a dict instead of string, and it would be a lot more readable
if you separated the fields outside of the Request class. When you have multiple header
fields to fill in, I find it better to use the add_header method as shown below.
import urllib, urllib2
def basic_authorization(user, password):
s = user + ":" + password
return "Basic " + s.encode("base64").rstrip()
url = "https://api.sandbox.paypal.com/v1/oauth2/token"
params = { "grant_type": client_credentials}
data = urllib.urlencode(params)
req = urllib2.Request(url, data)
req.add_header("Authorization",basic_authorization("XXX"))
req.add_header("Accept", "application/json")
req.add_header("User-Agent", "my-python-app/1")
response = urllib2.urlopen(req)

Categories

Resources