Python: requests lib post request not sending proper json format data - python

I am trying to connect to a very closed source database system via REST API to pull some data. The API so weird that it just gives you status code 400 & nothing much. No information or error pointing to what is wrong with the provided data. I am calling this API using postman & it is giving me proper response but when I use Python's requests lib to call this API I am getting 400 status (Which means there is something wrong with the provided data with the request).
This is my code.
def pull_data():
url = construct_url(configs.get("get_data_path"))
payload = json.dumps([
{
"SampleInterval": 600000,
"GetEnum": False,
"ResampleMethod": "Around",
"MinimumConfidence": 0,
"MaxRows": 100,
"TimeFormat": 6,
"ReductionData": "avg",
"TagName": [
"NC_AI3",
"NC_AI32"
],
"StartTime": "05/16/2022 08:49:26.000",
"EndTime": "05/16/2022 13:03:36.000",
"OutputTimeFormat": 6,
"EventSequence": 0
}
])
headers = {'Content-Type': 'application/json'}
res = requests.post(url, json=payload, verify=False, auth=HTTPBasicAuth(configs.get("user"), configs.get("password")), headers=headers)
print("----------", "Status Code", res.status_code, "-------")
I think somehow the json data sent via the request.post method is not getting recognised by the API. I think it is something to do with the fact that I am sending list of dict as json error not a usual dict as we do or see everywhere.
Can please someone tell if I am sending the json data correctly or not or is there any other way to do it?

Related

Getting different responses from postman vs. python API call

I'm trying get the same data from an API call in Postman using Python.
The call is relatively simple. It uses Basic Authorization that only requires the API key being passes as the username, and a dynamic component: csv_key variable that is passed from earlier codes.
I was able to successfully made the request (status code 200), but the response from Python is different from the one in Postman. It's missing all key-value pairs except the firs two: id and description.
I'm getting this response from postman:
response from postman
{
"id": "63c9c0927885bf003ecd3a1b",
"description": "Streaming analytics",
"download_url": "https://storage.googleapis.com/***-static/***.csv?GoogleAccessId=888211540537-r3m40kms2upicdr07e5rl2q67feg9loh%40developer.gserviceaccount.com&Expires=4070908800&Signature=WvuuKdddCFKjSNpst5n8yKFNR5qtC1m1o1mQZFWLHmKomJtc7npa6PbwfRoTj9FhIIqbta98VPOYKMGW89XaqXtITh15V%2Bf9opAD3BnuLjTzWC6X24RC5kMCZATXpp9DWi1Our061%2FdKlpUozi1ir7b8AwBWWf%2Bs8u5J6VoelvtEyiZIO4l%2FQdeJ26GqDLRgWElEMAlBE3TJo7m3UuE8gOQPsYBCwBSfLI1bTIytNOHZMUlWuVtMQxEHzUOujAp%2Fgqn1Q8TGGzy5GoeEmzw%2FD80xs%2BALjhT%2BxdiN9riG6%2BEcObrhPoudxl32jUhVH0EmGJwjgiJFQpz%2FLfKr86LrCQ%3D%3D",
"error": "Cannot read property 'email' of undefined",
"completed_at": "2023-01-19T22:13:39.219Z"
}
But I'm only getting the first two key-value pairs using a Python script of the same API call:
response from Python
csv key: 63c9c0927885bf003ecd3a1b
api url: https://api.eventive.org/temporary_exports/63c9c0927885bf003ecd3a1b
<Response [200]>
response:[{'id': '63c9c0927885bf003ecd3a1b', 'description': 'Streaming analytics'}]
Process finished with exit code 0
My code for the Python script is:
import requests
import json
url_for_key = 'https://api.***.org/reports/streams?event_bucket=63279b48d8f8f1009209694f&start=1674111600000&end=1674198000000&tz=America%2FDenver'
api_key = '*************************'
header = {'content-type': 'application/json'}
r1 = requests.get(url=url_for_key, auth=(api_key, ''))
csv_obj = [r1.json()]
csv_key = csv_obj[0]['temporary_export']
#print(csv_obj)
print(f'csv key: {csv_key}')
url_for_link = 'https://api.***.org/temporary_exports/{}'.format(csv_key)
print(f'api url: {url_for_link}')
r2 = requests.get(url=url_for_link, headers=header, auth=(api_key, ''))
print(r2)
print(f'response:{[r2.json()]}')
csv_key is the same as id. Could anyone help me understand what's going on?
Many thanks,

Problem on performing CRUD operation using Django REST API

Hey I am new to Django Rest Framework.I have recently created REST API name "api/studentapi" using django REST framework in local host. The CRUD operation works perfectly fine in browseable API. But When I try to access the same API from third party python file, I am not able to perform POST operation although I am able to perform GET operation.While performing POST operation the server reponse me as "Unsupported Media Type: /api/studentapi/".I am posting series of code images so that the stuffs gets more clear
The third party python app that I have created to access the "api/studentapi"
The file structure of my project
The model form that I have created
The serializer files that I have created
The urls code
And Finally the view file
Make sure you a passing the content type header during your post and put request, as that's how django_rest_framework understands which parser it will use. The Django rest framework supports content type of form-data, JSON, x-www-form-urlencoded and multipart out of the box.
If you're sending JSON data add the header to your request:
Content-Type: application/json
If you send form data or file(s) add the header:
Content-Type: multipart/form-data
If you're sending only form data use:
Content-Type: application/x-form-urlencoded
For your code this is how to add the header
r = request.post(
url=URL,
data=json_data,
headers= {
'Content-Type': 'application/json'
}
)
TL;DR:
You need to pass the payload as json argument in requests.post:
data = {
"name": "sa",
"roll": 1,
"city": "lam"
}
r = requests.post(url=URL, json=data)
Details:
As stated in the official documentation of requests library:
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload))
Please note that the above code will NOT add the Content-Type header
(so in particular it will NOT set it to application/json).
If you need that header set and you don’t want to encode 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)
import json
import requests
url = "https://127.0.0.1:8000/api/studentapi/"
data_response = {
"name": "sa",
"roll": 1,
"city": "lam"
}
data_json = json.dumps(data_response)
req = requests.post(url, data=data_json)

How to correctly call an API in Google Cloud Functions with a Python Function?

I am new to python and want to fetch data from an API via Google Cloud Functions so that I can store the data in Google Cloud Storage afterwards.
The data is available in JSON format and I want to transform it in a table via pandas.
Since I am really unsure about the correct syntax I'd like to know how I have to call the function test_topic - The following code doesn't work for me. I get no error message but also I get no result.
What do I have to do that I get the table as a result?
import requests
import pandas as pd
def test_topic(df):
url = "https://api.domain.com/v1/"
payload={}
headers = {}
parameters = {
"api_key": "1234567890",
"start_date": "2020-01",
"end_date": "2021-01",
"format": "json"
}
response = requests.request("GET", url, headers=headers, data=payload, params=parameters)
df = response.json()['visits']
pd.DataFrame(df)
Your first issue is that you probably need to authenticate your request against the Cloud Function. Unless the Cloud Function was deployed --allow-unauthenticated (permitting anyone), you're going to have to authenticate requests using an access (?) token (TOKEN):
token = os.getenv("TOKEN")
headers=["Authorization"] = "Bearer: {token}".format(token=token)}
For development purposes, you can grab a token using gcloud and export this to your code:
export TOKEN=$(gcloud auth print-access-token)
python3 main.py
You should also:
headers["Accept"] = "application/json"
For debugging, you should consider:
json_response = response.json()
print(json_response)
before you try to access visits, perhaps:
if "visits" in json_response:
# JSON response contains "visits"
else:
# JSON response does not contain "visits"

How to send a python requests post for an equivalent curl command?

Hi
Following curl command works and am trying to post the same (with a different JSON data )using requests.post and running into below error shown,any guidance on what is wrong?
curl -vk "https://splunk-hec.company.com:8088/services/collector" -H "Authorization: {token id }" -d '{"sourcetype": "source","index":"indexname", "event": {"a": "value1", "b": ["value1_1", "value1_2"]}}'
PYTHON CODE:-
_raw = {
"Total_radar_count":"999",
"Analyze":{
"Screen":{"count":110,"radar_link":"change://problem/50411162&42639456&44776863&43703933"},
"Investigate":{"count":065,"radar_link":"change://problem/50411162&42639456&44776863&43703933"},
"Review":{"count":106,"radar_link":"change://problem/50411162&42639456&44776863&43703933"}
},
"timestamp": int(time.time()) # Can also use datetime.datetime.now().isoformat()
}
url = 'https://splunk-hec.company.com:8088/services/collector?sourcetype=source?index=indexname'
json = _raw
auth_token = 'token id'
head = {'Authorization': auth_token}
response = requests.post(url, json=json, headers=head)
print(response)
print (response.reason)
print(response.json())
ERROR:-
<Response [400]>
Bad Request
{u'text': u'No data', u'code': 5}
400 (Bad Request) can be many things; see the doc at https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400 . Next debugging step is to get out wireshark and look at the difference between the two requests. Obviously your data is different between the two, so it could be rejecting it just based on what it expects.
Also check the server-side log. Chances are the real error is in there.
Try using
requests.post(url, headers=head, data=json.dumps(json))
You also need to import json package but don't wory it is a built in package
This question is quite old. However, I thought to share this as I think it may helpful others. Just try adding "event": for you json post data.
response = requests.post(url, json={"event": json}, 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":[]}}]]'

Categories

Resources