Passing both dict and json to a url - python

I have to use a webservice endpoint that needs both JSON and non-json in the query and I don't know how to do it with the requests package. the same code provided has http.client in it, and I don't have access to that package in this project for unrelated reasons
The example code is:
import http.client
conn=http.client.HTTPSConnection('some.url')
payload="{\"some_json_dict_key\": \"some_json_dict_value\"}"
headers={'content-type': "application/json", 'accept': "application/json"}
conn.request("POST", "/someEndpoint?param1=value_of_param1", payload, headers)
res = conn.getresponse()
data = res.read().decode('utf-8')
The code i have tried which doesnt work:
import requests
headers={'content-type': "application/json", 'accept': "application/json"}
params={'param1': 'value_of_param1'}
json_payload = "{\"some_json_dict_key\": \"some_json_dict_value\"}"
url = 'https://some.url/someEndpoint'
response = requests.post(url, headers=headers, data=params, json=json_payload)
however that doesn't seem to work i get the exception
{'httpMessage': 'Bad Request', 'moreInformation': 'The body of the request, which was expected to be JSON, was invalid, and could not be decoded. The start of an object { or an array [ was expected.'}

According to the documentation:
Instead of encoding the dict yourself, you can also pass it directly using the json parameter (added in version 2.4.2) and it will be encoded automatically:
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, json=payload)
but you're passing a string into the json parameter (I admit that the error message could be clearer). All other parameters are json/dict objects. Make json_payload an actual dictionary.
json_payload = {"some_json_dict_key": "some_json_dict_value"} # real dictionary, not a json string
url = 'https://some.url/someEndpoint'
response = requests.post(url, headers=headers, data=params, json=json_payload)

You must realize that a POST request can pass information in two places: In the body (data) of the request, and in the URL string (the request parameters, like a GET request does). In the example you didn't fully emulate, the parameters are in the URL string, and the body, according to the error message you got back, must consist of a single JSON object. Therefore, use the params dictionary for the URL parameters, like this:
response = requests.post(url, headers=headers, params=params, data=json_payload)
That ought to do it, unless there are other details to take care of.

Related

python > requests module > post > headers not working

Why I'm getting a response like this? I tried to ask people on Discord and no one could explain.
>>>import requests
>>>api_url = "my_url"
>>>headers = {"Content-type": "application/json"}
>>>res = requests.post(api_url, "text to post", headers=headers)
>>>res.json()
{'message': '400: Bad Request', 'code': 0}
since you've received this response from the server:
{'message': '400: Bad Request', 'code': 0}
It indicates that you have actually hit a server endpoint, so you've probably just not included all the data that the server was expecting for the request.
Note that the docs specify that 'data' should be "(optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the Request", so probably best practice to encode your text beforehand like:
my_text = "some json encoded text"
requests.post(api_url, my_text.encode("ascii"), headers = headers)
Double check the data you are sending (especially spelling) matches what the server requires for the request.
Try this:
import requests
import json
api_url = "my_url"
body = {'xxx': 'text to post'}
headers = {"Content-type": "application/json"}
res = requests.post(api_url, data=json.dumps(body), headers=headers)
res.json()

requests.post returns isSuccess:false even though Postman returns true

I am trying to post some information into an API based on their recommended format. When I use Postman( tool to test APIs), I see that the response has the isSuccess flag set to true. However, when I write the same code in Python using the requests library, I get the isSuccess flag as false
As mentioned about, I verified the headers and the json data object, both are the same yet the results defer
import requests
data = {"AccountNumber":"100007777",
"ActivityID":"78",
"ActivityDT":"2019-08-07 12:00:00",
"ActivityValue":"1"
}
url = "http://<IP>/<API_PATH>"
headers = {
"X-Tenant":"Default",
"Content-Type":"application/json"
}
response = requests.post(url,data=data, headers = headers)
print(response.content)
This code should successfully post the data and I should get a isSuccess:true in my response variable.
Can anyone help me figure out what might be wrong?
Can you try to change;
response = requests.post(url,data=data, headers = headers)
to;
response = requests.post(url,json=data, headers = headers)
or;
response = requests.post(url,body=data, headers = headers)

How to call an API using Python Requests library

I can't figure out how to call this api correctly using python urllib or requests.
Let me give you the code I have now:
import requests
url = "http://api.cortical.io:80/rest/expressions/similar_terms?retina_name=en_associative&start_index=0&max_results=1&sparsity=1.0&get_fingerprint=false"
params = {"positions":[0,6,7,29]}
headers = { "api-key" : key,
"Content-Type" : "application/json"}
# Make a get request with the parameters.
response = requests.get(url, params=params, headers=headers)
# Print the content of the response
print(response.content)
I've even added in the rest of the parameters to the params variable:
url = 'http://api.cortical.io:80/rest/expressions/similar_terms?'
params = {
"retina_name":"en_associative",
"start_index":0,
"max_results":1,
"sparsity":1.0,
"get_fingerprint":False,
"positions":[0,6,7,29]}
I get this message back:
An internal server error has been logged # Sun Apr 01 00:03:02 UTC
2018
So I'm not sure what I'm doing wrong. You can test out their api here, but even with testing I can't figure it out. If I go out to http://api.cortical.io/, click on the Expression tab, click on the POST /expressions/similar_terms option then paste {"positions":[0,6,7,29]} in the body textbox and hit the button, it'll give you a valid response, so nothing is wrong with their API.
I don't know what I'm doing wrong. can you help me?
The problem is that you're mixing query string parameters and post data in your params dictionary.
Instead, you should use the params parameter for your query string data, and the json parameter (since the content type is json) for your post body data.
When using the json parameter, the Content-Type header is set to 'application/json' by default. Also, when the response is json you can use the .json() method to get a dictionary.
An example,
import requests
url = 'http://api.cortical.io:80/rest/expressions/similar_terms?'
params = {
"retina_name":"en_associative",
"start_index":0,
"max_results":1,
"sparsity":1.0,
"get_fingerprint":False
}
data = {"positions":[0,6,7,29]}
r = requests.post(url, params=params, json=data)
print(r.status_code)
print(r.json())
200
[{'term': 'headphones', 'df': 8.991197733061748e-05, 'score': 4.0, 'pos_types': ['NOUN'], 'fingerprint': {'positions': []}}]
So, I can't speak to why there's a server error in a third-party API, but I followed your suggestion to try using the API UI directly, and noticed you're using a totally different endpoint than the one you're trying to call in your code. In your code you GET from http://api.cortical.io:80/rest/expressions/similar_terms but in the UI you POST to http://api.cortical.io/rest/expressions/similar_terms/bulk. It's apples and oranges.
Calling the endpoint you mention in the UI call works for me, using the following variation on your code, which requires using requests.post, and as was also pointed out by t.m. adam, the json parameter for the payload, which also needs to be wrapped in a list:
import requests
url = "http://api.cortical.io/rest/expressions/similar_terms/bulk?retina_name=en_associative&start_index=0&max_results=1&sparsity=1.0&get_fingerprint=false"
params = [{"positions":[0,6,7,29]}]
headers = { "api-key" : key,
"Content-Type" : "application/json"}
# Make a get request with the parameters.
response = requests.post(url, json=params, headers=headers)
# Print the content of the response
print(response.content)
Gives:
b'[[{"term":"headphones","df":8.991197733061748E-5,"score":4.0,"pos_types":["NOUN"],"fingerprint":{"positions":[]}}]]'

python requests POST 400 error

I've been looking to many questions similar to mine but I could not find a solution.
I'm using requests to perform a POST request. I've tried a lot of combinations inside the request but nothing returns a 201 ok.
Here is my code:
import json
import requests
if __name__ == '__main__':
headers = {'content-type' : 'application/json'}
url = "http://myserver/ext/v3.1/test_device"
message = {"atribute_a": "value", "atribute_b": "valueb"}
params = {"priority":"normal"}
r = requests.post(url, params=params, headers=headers, data = json.dumps(message) )
print(r)
I've also tried withou json.dumps but it also gives me 400 bad request. I've also tried to add the params directly to the url like: ...?priority=normal but with no success.
The easiest technique is to use json instead of data as followed:
requests.post(url, headers=headers, params=params, json=data)
Based on the comments, your server is actually expecting data as a stringified JSON object.
As far as the params are concerned, it'd most probably help if they're declared as a tuple of tuples (or a dict of dicts)
Try the following -
headers = {
'content-type': 'application/json',
}
params = (
('priority', 'normal'),
)
data = {
"atribute_a": "value",
"atribute_b": false
}
requests.post(url, headers=headers, params=params, data=str(data))

Google returning 400 Parse Error

I've recently been getting a 400 bad request parse error when making a request to my timeline_url.
Im posting to this url timeline_url = 'https://www.googleapis.com/mirror/v1/timeline'
EDIT
Here is the code:
headers = {'Content-Type': 'application/json',
'Authorization' : 'Bearer %s' % access_token}
body = {"text" : "Waddup doe!"}
""" ***********THIS IS RETURNING ERROR 400 PARSE ERROR***********"""
send_request(timeline_url, headers, 'POST',body)
The send_request method is using requests
req = requests.post(url, data=body, headers=headers)
I'm just trying to insert plain text to my timeline.
body_bytes = sys.getsizeof(body)
headers['Content-Length'] = body_bytes
This is inserting an incorrect value into your request headers. sys.getsizeof describes how large the data structure is -- including pointers, counters, etc. It does NOT describe how many bytes the string representation takes on the HTTP stream.
Just delete these lines; requests will fill in Content-Length automatically.
You don't describe how you json-encode the payload. Perhaps you need to do this:
req = requests.post(url, data=json.dumps(body), headers=headers)
See: http://docs.python-requests.org/en/latest/user/quickstart/#more-complicated-post-requests

Categories

Resources