How to perform this python post request - python

I am new to python requests and do not know how to call this API with a post request.
This is the information I got:
POST /whatcaristhat?key=<CarsXE_API_Key> HTTP/1.1
Host: http://api.carsxe.com
Content-Type: text/plain
https://upload.wikimedia.org/wikipedia/commons/4/44/2019_Acura_RDX_A-Spec_front_red_4.2.18.jpg
What I got so far is:
import requests
api_key = 12345
url = f'http://api.carsxe.com/whatcaristhat?key={api_key}'
data = b'https://upload.wikimedia.org/wikipedia/commons/4/44/2019_Acura_RDX_A-Spec_front_red_4.2.18.jpg'
headers = {'Content-Type' : 'text/plain'}
r = requests.post(url,
data=data,
headers=headers)
print(r.status_code)
But I get this error:
TypeError: a bytes-like object is required, not 'str'

This API takes either an image URL or a base64 encoded image. As of now, data is defined as a set. The fix is pretty straightforward:
data = b'https://upload.wikimedia.org/whatevertheurlis.jpg'

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

Error passing curl -d parameter in requests library

I have a curl POST request that works perfectly in the terminal (macOS), returning a csv as expected. The following format is provided in the RJMetrcis documentation (see "Export figure data"). Here is the curl request in bash:
 curl -d "format=csv&includeColumnHeaders=1" -H "X-RJM-API-Key: myAPIkey" https://api.rjmetrics.com/0.1/figure/0000/export
My objective is to implement the exact same curl request in Python using requests. When I input the same parameters as a POST request, the code does not work returning an error:
import requests
headers = {'X-RJM-API-Key: myAPIkey'}
data= {'format=csv&includeColumnHeaders=1'}
url = "https://api.rjmetrics.com/0.1/figure/0000/export"
response = requests.post(url, data, headers)
This returns the error:
TypeError: memoryview: a bytes-like object is required, not 'str'
On the second try:
response = requests.post(url, data=data, headers=headers)
returns
AttributeError: 'set' object has no attribute 'items'
What is the correct format in python for constructing a POST request so that it matches the data = {'key':'value'} convention, and returns a csv?Any help would be appreciated translating the bash curl POST into a python POST request
Here you are passing a set and you are expected to pass a dict or str object
data= {'format=csv&includeColumnHeaders=1'}
Replacing with
data= {'format':'csv&includeColumnHeaders=1'}
Should fix it.
On the other hand by seeing your curl request..
It all depends how you want to pass the data, following code (passing the data payload as a string) will post the data directly, that will be the equivalent to --data-raw in curl
import requests
url = "https://api.rjmetrics.com/0.1/figure/0000/export"
payload = "'{\"format\":\"csv&includeColumnHeaders=1\"}'"
headers = {
'X-RJM-API-Key': 'myAPIkey'
}
response = requests.request("POST", url, headers=headers, data = payload)
print(response.text.encode('utf8'))

Passing both dict and json to a url

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.

Passing file and data to requests, error at every turn

Python 3.6.7, Requests 2.21.0
I have an issue that gives me a new error at every solution.
What I want: To send a file with data in a POST command using the requests library.
url_upload = BASE_URL + "upload?action=save"
data = {'data':{'name':'test.txt','contenttype':'text/plain', 'size':37}}
files = {'file': open('/home/user/test.txt', 'rb')}
req = session.post(url=url_upload, files=files, data=data)
The end server is using Spring (I assume) and the response text contains this error:
"net.sf.json.JSONException: A JSONObject text must begin with \'{\' at character 1 of name"
So, I try
data = json.dumps(data)
But, of course requests doesn't want that:
ValueError: Data must not be a string.
If I add the headers:
headers = {'Content-type': 'multipart/form-data'}
org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
Help would be appreciated.
What I needed to do was:
req = session.post(url=url_upload, files=files, data={'data': json.dumps(data)})
That way I'm giving the function variable 'data' the form-data variable name 'data' which contains the variable that has the key 'data'...
http://www.trekmate.org.uk/wp-content/uploads/2015/02/Data-star-trek-the-next-generation-31159191-1024-768.png

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