Sending a JSON string as a post request - python

rocksteady's solution worked
He did originally refer to dictionaries. But the following code to send the JSON string also worked wonders using requests:
import requests
headers = {
'Authorization': app_token
}
url = api_url + "/b2api/v1/b2_get_upload_url"
content = json.dumps({'bucketId': bucket_id})
r = requests.post(url, data = content, headers = headers)
I'm working with an API that requires me to send JSON as a POST request to get results. Problem is that Python 3 won't allow me to do this.
The following Python 2 code works fine, in fact it's the official sample:
request = urllib2.Request(
api_url +'/b2api/v1/b2_get_upload_url',
json.dumps({ 'bucketId' : bucket_id }),
headers = { 'Authorization': account_authorization_token }
)
response = urllib2.urlopen(request)
However, using this code in Python 3 only makes it complain about data being invalid:
import json
from urllib.request import Request, urlopen
from urllib.parse import urlencode
# -! Irrelevant code has been cut out !-
headers = {
'Authorization': app_token
}
url = api_url + "/b2api/v1/b2_get_upload_url"
# Tested both with encode and without
content = json.dumps({'bucketId': bucket_id}).encode('utf-8')
request = Request(
url=url,
data=content,
headers=headers
)
response = urlopen(req)
I've tried doing urlencode(), like you're supposed to. But this returns a 400 status code from the web server, because it's expecting pure JSON. Even if the pure JSON data is invalid, I need to somehow force Python into sending it.
EDIT: As requested, here are the errors I get. Since this is a flask application, here's a screenshot of the debugger:
Screenshot
Adding .encode('utf-8') gives me an "Expected string or buffer" error
EDIT 2: Screenshot of the debugger with .encode('utf-8') added

Since I have a similar application running, but the client still was missing, I tried it myself.
The server which is running is from the following exercise:
Miguel Grinberg - designing a restful API using Flask
That's why it uses authentication.
But the interesting part: Using requests you can leave the dictionary as it is.
Look at this:
username = 'miguel'
password = 'python'
import requests
content = {"title":"Read a book"}
request = requests.get("http://127.0.0.1:5000/api/v1.0/projects", auth=(username, password), params=content)
print request.text
It seems to work :)
Update 1:
POST requests are done using requests.post(...)
This here describes it well : python requests
Update 2:
In order to complete the answer:
requests.post("http://127.0.0.1:5000/api/v1.0/projects", json=content)
sends the json-string.
json is a valid parameter of the request and internally uses json.dumps()...

Related

Python requests library for oauth token

So i was following the guide for getting a OAUTH token from https://developer.spotify.com/documentation/general/guides/authorization/client-credentials/
I tried doing a python requests library of the above equivalent code but i got response 400 from the server. May I know where i am going wrong?
import requests
import json
import clientidandsecret
headers ={"Authorization": "Basic " + clientidandsecret.C_ID +":" +clientidandsecret.C_SECRET}
form = {"form":{"grant_type" :"client_credentials"}, "json":"true"}
result = requests.post("https://accounts.spotify.com/api/token", headers=headers, data=form)
print(result)
Your variable form is a Dict, if you want to use the parameter data in requests it needs to be a string, this will fix it:
import json
...
result = requests.post(url, headers=headers, data=json.dumps(form))
Or even better:
result = requests.post(url, headers=headers, json=form)

Python requests module working in postman but on with python Invalid request body/header

I am using the postman tool to send the requests to the api server and trying to get the code snip-it from code section of postman, but somehow the same code is not working with python
this is the code :
import requests
import json
url = "http://127.0.0.1:3333/api/v1/solve"
payload={'FileLocation': '/var/opt/rcm_dms/reg'}
files=[
('regChallengeFile',('gudsgtcnsrk_reg_challenge.json',open('/home/system/Music/gudsgtcnsrk_reg_challenge.json','rb'),'application/json'))
]
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.text)
output : {"statusCode":"DM-6-4002","statusMessage":"Invalid request body/header"}\n
I am using the postman tool to send the requests to the api server and trying to get the code snip-it from code section of postman, but somehow the same code is not working with python
this is the code :
output : {"statusCode":"DM-6-4002","statusMessage":"Invalid request body/header"}\n
What is wrong in this example , any suggestions
Single quotes should be on both side of key FileLocation payload={'FileLocation': '/var/opt/rcm_dms/reg'} instead of payload={FileLocation': '/var/opt/rcm_dms/reg'}.
If you still get the error, check the format of value assigned in files variable i.e.,[('regChallengeFile',('gudsgtcnsrk_reg_challenge.json',open('/home/system/Music/gudsgtcnsrk_reg_challenge.json','rb'),'application/json'))]

I want to send a Python request to an ASP site but the site show access denied

Site url is http://rajresults.nic.in/resbserx18.htm when send data, but when response comes URL changes in ASP. So which URL user need to send request ASP or html?
Request:
import requests
# data for get result
>>> para = {'roll_no':'2000000','B1':'Submit'}
# this is url where data is entered and get asp response
>>> url = 'http://rajresults.nic.in/resbserx18.htm'
>>> result = requests.post(url,data=para)
>>> result.text
Response
'The page you are looking for cannot be displayed because an invalid method (HTTP verb) is being used.'
Okay after a little bit of work, I found it's some issue with the headers.
I did some trial and error, and found that it checks to make sure the Host header is set.
To debug this, I just incrementally removed chrome's request headers and found which one this web service was particular about.
import requests
headers = {
"Host": "rajresults.nic.in"
}
r = requests.post('http://rajresults.nic.in/resbserx18.asp',
headers = headers,
data = {'roll_no': 2000000, 'B1': 'Submit'}
)
print(r.text)

Fetch data from a service using python

I need to write a python that accesses an internal to organization URL. I have an auth token.
How should my python look
At the moment I have this
import json
import requests
from pprint import pprint
path='/Users/Documents/sample_2.dat'
for url in open(path):
print url[1:-2]
headers = {'Content-type': 'application/json'}
response = requests.get(url[1:-2], headers=headers)
field_value = response.json()
print field_value["externals"]
sample_2.dat has 2 urls 1 below other
Example:
"http://xxx.abc.com/mfc/abc/v1/ext_info?id=1841261718,3421035156,B0185LBO7I,B0082SIL3K,B000PS8P3Q,B00G441OMY,0793522048,B00B12D2WY,3637015080,B00TNOUNVU&fields=ex.title,ex.url&fieldgroups=default"
"http://xxx.abc.com/mfc/abc/v1/ext_info?id=0553153617,B003W0CI6Y,B000R08E7Y,B001O2SAAU,B00B1MP3MG,B00QRHJBPU,B00007B4DC,0852597088,B0000003H4,1937715213&fields=ex.title,ex.url&fieldgroups=default"
Perhaps this might be useful, which can be found in the documentations
For GET requests that might require basic authentication, you can
include the auth paramter as follows:
response = requests.get('https://api.github.com/user', auth=('user','pass'))
As you can see, it is as simple as adding the auth parameter inside your get request.

Python Requests data parameter not working properly

I'm using Requests http://docs.python-requests.org/en/latest/
I'm trying to do a simple POST request with some extra headers. I don't understand the following behavior.
opener = requests.Session()
data = {"payload" : { "id": 1, "pwd": "mypass"}
headers = {"Content-Type":"application/json"}
url = "https://mysite.com/login"
# THIS WORKS
opener.post(url, data)
# THIS DOES NOT WORK
opener.post(url, json.dumps(data))
# THIS DOES NOT WORK
opener.post(url, data=data, headers=headers)
# THIS WORKS
opener.post(url, data=json.dumps(data), headers=headers)
It seems that the post method expects a dict normally and does not work when I convert that dict to a string. I can login using the former but I can't using the latter.
However, when I supply extra headers information, it seems the post method works the extact opposite way, it expects a string for the data. On the server side, the first version throws an error while the second version works with headers.
What is the reason for this behavior?

Categories