How can I post payload with requests in python? - python

This is what I observed with f12 in chrome:
The payload here doesn't seem like json data since there is 89:42 in the front.
payload = ["auth",{"form":{"id":"xxxx","email":"xxx#xxx"}}]
resp = requests.post(url, json=payload, headers=headers)
print(resp.status_code)
payload = '89:42["auth",{"form":{"id":"xxxx","email":"xxx#xxx"}}]'
resp = requests.post(url, data=payload, headers=headers)
print(resp.status_code)
The status code of the above resp are both 400(bad request). How can I post it correctly?
[EDIT] I actually used Session to maintain the session. I'v also tried to change the content-type to application/json. But it didn't work. And as your can see in the picture, the default content-type seen with f12 is text/plain.
[EDIT] Some said the data or json argument must be a dict. Does it means that I should rewrite 89:42["auth",{"form":{"id":"xxxx","email":"xxx#xxx"}}] to change its type to dict? How should I do this?

From reading the requests documentation, you need to pass your payload as a dictoinary like this:
response = requests.post('https://httpbin.org/post', data = {'key':'value'})

Related

How can I make post requests with querystrings using sessions in Python?

i'm using requests module and i'm interested in sending a post request with querystrings using sessions, how can I do that? I haven't found anything related with request.Sessions and querystrings
with Sessions (it returns me a http 500 response code)
response = self.session.post(self.url, data = payload, headers = self.headers, params = querystring)
without Sessions ( it works fine)
response = requests.request("POST", self.url, json=payload, headers=self.headers, params=querystring)
Maybe you can provide the url and a little bit more code.
In the session example you pass data=payload.
In the second example json=payload.
Did you create the session correctly?

Post a string as multipart/form-data using requests

I am posting to an API that seems to insist on receiving XML data as multipart/form-data with the name (file name?) xml. It works in postman but I can't get it to work using Python's requests. This is my Python code (based on https://stackoverflow.com/a/24443309/1011724):
requests.post(callpro_url,
files={'xml':('data.xml',result)},
verify=False).text
where result is a string containing XML. If I try this code I get the response:
xml post field is empty
which is the response this API give if you don't use the multipart/form-data header.
If I generate code from the working postman post I get something like this (slightly redacted):
import requests
url = "https://blablabla.blablab.com/blabla/api.php"
querystring = {"mode":"import","hash":"redacted-hash","xml":"\"xml\""}
payload = "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"xml\"\r\n\r\n<?xml version=\"1.0\" ?>\n<importdata>\n --redacted-XML-- \n</importdata>\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--"
headers = {
'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
'cache-control': "no-cache",
'postman-token': "8d3ec8ee-784e-3a65-5240-cf1a9534d1c4"
}
response = requests.request("POST", url, data=payload, headers=headers, params=querystring)
print(response.text)
Executing this code in Python, it gives the correct response.
Note that the params=querystring part in the postman code is taken care of in the URL in my code.
I'm confused by the payload in the postman code. It adds things like Content-Disposition and name in the string. I assume that I can put this stuff in the tuple in the files parameter but I'm not sure how to to do it. I've tried files={'xml':('data.xml',result,'form-data')} for example and also files={'xml':('data.csv',result)} and {'xml':('xml',result)}.
Also, the postman code explicitly defines the header as
'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"
whereas the requests documentation say that I should never explicitly define the headers in that way. However the postman code works and my code does not.
Any suggestions?
I don't know if this is worth answering or if I should delete the question but what was needed was to name the file "xml" not xml. so this works:
requests.post(callpro_url,
files={'xml':('"xml"',result)},
verify=False).text

Python request resulting in blank response

I'm relatively new to Python so would like some help, I've created a script which simply use the request library and basic auth to connect to an API and returns the xml or Json result.
# Imports
import requests
from requests.auth import HTTPBasicAuth
# Set variables
url = "api"
apiuser = 'test'
apipass = 'testpass'
# CALL API
r = requests.get(url, auth=HTTPBasicAuth(apiuser, apipass))
# Print Statuscode
print(r.status_code)
# Print XML
xmlString = str(r.text)
print(xmlString)
if but it returns a blank string.
If I was to use a browser to call the api and enter the cretentials I get the following response.
<Response>
<status>SUCCESS</status>
<callId>99999903219032190321</callId>
<result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Dummy">
<authorFullName>jack jones</authorFullName>
<authorOrderNumber>1</authorOrderNumber>
</result>
</Response>
Can anyone tell me where I'm going wrong.
What API are you connecting to?
Try adding a user-agent to the header:
r = requests.get(url, auth=HTTPBasicAuth(apiuser, apipass), headers={'User-Agent':'test'})
Although this is not an exact answer for the OP, it may solve the issue for someone having a blank response from python-requests.
I was getting a blank response because of the wrong content type. I was expecting an HTML rather than a JSON or a login success. The correct content-type for me was application/x-www-form-urlencoded.
Essentially I had to do the following to make my script work.
data = 'arcDate=2021/01/05'
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
r = requests.post('https://www.deccanherald.com/getarchive', data=data, headers=headers)
print(r.status_code)
print(r.text)
Learn more about this in application/x-www-form-urlencoded or multipart/form-data?
Run this and see what responses you get.
import requests
url = "https://google.com"
r = requests.get(url)
print(r.status_code)
print(r.json)
print(r.text)
When you start having to pass things in your GET, PUT, DELETE, OR POST requests, you will add it in the request.
url = "https://google.com"
headers = {'api key': 'blah92382377432432')
r = requests.get(url, headers=headers)
Then you should see the same type of responses. Long story short,
Print(r.text) to see the response, then you once you see the format of the response you get, you can move it around however you want.
I have an empty response only when the authentication failed or is denied.
The HTTP status is still ≤ 400.
However, in the header you can find :
'X-Seraph-LoginReason': 'AUTHENTICATED_FAILED'
or
'X-Seraph-LoginReason': 'AUTHENTICATED_DENIED'
If the request is empty, not even a status code I could suggest waiting some time between printing. Maybe the server is taking time to return the response to you.
import time
time.sleep(5)
Not the nicest thing, but it's worth trying
How can I make a time delay in Python?
I guess there are no errors during execution
EDIT: nvm, you mentioned that you got a status code, I thought you were literally geting nothing.
On the side, if you are using python3 you have to use Print(), it replaced Print

Making a successful Python HTTP POST Request

I am trying to write a python script that will make a request to a desktop application listening to 8080 port. The below is the code that I use to make the request.
import requests
payload = {"url":"abcdefghiklmnopqrstuvwxyz=",
"password":"qertyuioplkjhgfdsazxvnm=",
"token":"abcdefghijklmn1254786=="}
headers = {'Content-Type':'application/json'}
r = requests.post('http://localhost:9015/login',params = payload, headers=headers)
response = requests.get("http://localhost:9015/login")
print(r.status_code)
After making the request, I get a response code of 401.
However, when I try the same using the Postman app, I get a successful response. The following are the details I give in Postman:
URL: http://localhost:9015/login
METHOD : POST
Headers: Content-Type:application/json
Body: {"url":"abcdefghiklmnopqrstuvwxyz=",
"password":"qertyuioplkjhgfdsazxvnm=",
"token":"abcdefghijklmn1254786=="}
Can I get some suggestions on where I am going wrong with my python script?
You pass params, when you should pass data, or, even better, json for setting Content-Type automatically. So, it should be:
import json
r = requests.post('http://localhost:9015/login', data=json.dumps(payload), headers=headers)
or
r = requests.post('http://localhost:9015/login', json=payload)
(params adds key-value pairs to query parameters in the url)

Executing URLs in Python similar to curl in Linux - JenkinsAPI

I am trying to trigger some builds using a shell script by doing the following :
export url='http://test.com';
export job_name='MY_JOB_NAME';
jso="{\"parameter\": [{\"name\":\"BRANCH\",\"value\":\"master\"}, {\"name\":\"GITURL\",\"value\":\"https://github.test.com/test/test.git\"}]}";
curl $url/job/$job_name/build --data-urlencode json="$jso";
This works fine, but when I try to convert it to a python equivalent, it doesn't seem to trigger the URL:
import requests
import json
url='http://test.com/job/MY_JOB_NAME/build'
params={'name':'release_1.5', 'GITURL':'https://github.test.com/test/test.git'}
payload = json.dumps(params)
resp = requests.get(url=url, data=payload)
This executes without any error, but it does not trigger a build on my CI machine.
There are quite a few things you're doing wrong here. The first thing which I hope is apparent is that the JSON data you're sending is completely different.
Beyond that, the primary issue you're having here is that your curl is doing a POST with urlencoded data in the BODY, and your python request is doing a GET with urlencoded data as separate parameters in the url. Change your .get to a .post, and the params= to data= and you should be a whole lot closer to your intended goal.
resp = requests.post(url=url, data={'json':payload})
Also note, I embedded your payload into a key as json, as that's what is happening in your curl. I'm not fully aware of your implementation details, but I hope that this helped put you on the right track.
Add the content-type to the header of the request, i.e.:
headers = {'content-type': 'application/json'}
...
resp = requests.get(url=url, params=payload, headers=headers)

Categories

Resources