Response' object is not subscriptable Python http post request - python

I am trying to post a HTTP request. I have managed to get the code to work but I am struggling returning some of the result.
The result looks like this
{
"requestId" : "8317cgs1e1-36hd42-43h6be-br34r2-c70a6ege3fs5sbh",
"numberOfRequests" : 1893
}
I am trying to get the requestId but I keep getting the error Response' object is not subscriptable
import json
import requests
workingFile = 'D:\\test.json'
with open(workingFile, 'r') as fh:
data = json.load(fh)
url = 'http://jsontest'
username = 'user'
password = 'password123'
requestpost = requests.post(url, json=data, auth=(username, password))
print(requestpost["requestId"])

The response object contains much more information than just the payload. To get the JSON data returned by the POST request, you'll have to access response.json() as described in the example:
requestpost = requests.post(url, json=data, auth=(username, password))
response_data = requestpost.json()
print(response_data["requestId"])

You should convert your response to a dict:
requestpost = requests.post(url, json=data, auth=(username, password))
res = requestpost.json()
print(res["requestId"])

the response is not readable so you need to convert that into a readable format,
I was using python http.client
conn = http.client.HTTPConnection('localhost', 5000)
payload = json.dumps({'username': "username", 'password': "password"})
headers = {'Content-Type': 'application/json'}
conn.request('POST', '/api/user/register', payload, headers)
response = conn.getresponse()
print("JSON - ", response.read())
and for request, you can see the answers above
sometimes you have to use json.loads() function to convert the appropriate format.

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()

In python, how can we connect to API using a certificate, subscription key?

I am trying to connect to an api for which I was provided with link, certificate(.p12) and subscription key.
Having some issue while giving the certificate details. I am trying in the following 2 ways:
1.
import json
from requests_pkcs12 import get,post
url = 'https://....'
pkcs12_filename = '<certificate file path>'
pkcs12_password = '<certificate password>'
headers = {
# Request headers
'Subscription-Key': '<subscription key>',}
response = post(url, headers=headers, verify=False, pkcs12_filename=pkcs12_filename,pkcs12_password=pkcs12_password)
print(response.status_code)
import http.client, urllib.request, urllib.parse, urllib.error, base64
#file = "<certificate path>"
headers = {
'Subscription-Key': '<subscriptionkey>',
#'cert' : crypto.load_pkcs12(open(file, 'rb').read(), "<password>").get_certificate(),
'file' : '<certificate path>',
'password':'<certificate password>',}
params = urllib.parse.urlencode({
})
conn = http.client.HTTPSConnection('<api main link>')
conn.request("GET", "<api remaining link>" , params, headers)
response = conn.getresponse()
data = response.read()
print("Status: {} and reason: {}".format(response.status, response.reason))
conn.close()
I am new to API concept. Will someone help me over this?
Refered to this link: How to use .p12 certificate to authenticate rest api
But didn't get what i need to put in data variable

How can I post a PDF to AWS lambda

I have AWS Lambda set up.
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': json.dumps(event)
}
I would like to POST in a PDF file so that I can operate on it in my lambda function.
Here is my POST code
import requests
headers = {
'X-API-KEY':'1234',
'Content-type': 'multipart/form-data'}
files = {
'document': open('my.pdf', 'rb')
}
r = requests.post(url, files=files, headers=headers)
display(r)
display(r.text)
I am getting the error:
<Response [400]>
'{"message": "Could not parse request body into json: Unexpected character (\\\'-\\\' (code 45)) in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value
How can I POST over my PDF and be able to properly send over my PDF and access it in Lambda?
Note:
I am successful if I do this:
payload = '{"key1": "val1","key2": 22,"key3": 15,"key4": "val4"}'
r = requests.post(url = URL, data=payload, headers=HEADERS)
It is just the PDF part which I can't get
I figured it out. Took me a ton of time but I think I got it. Essentially it's all about encoding and decoding as bytes. Didn't have to touch the API Gateway at all.
Request:
HEADERS = {'X-API-KEY': '12345'}
data = '{"body" : "%s"}' % base64.b64encode(open(path, 'rb').read())
r = requests.post(url, data=data, headers=HEADERS)
In lambda
from io import BytesIO
def lambda_handler(event, context):
pdf64 = event["body"]
# Need this line as it does 'b'b'pdfdatacontent'.
pdf64 = pdf64[2:].encode('utf-8')
buffer = BytesIO()
content = base64.b64decode(pdf64)
buffer.write(content)
I found this worked quite well for me:
Request
import requests
file_loc = 'path/to/test.pdf'
data = open(file_loc,'rb').read() #this is a bytes object
r = requests.post(url, data=data)
r.ok #returns True (also a good idea to check r.text
#one-liner
requests.post(url, data=open(file_loc,'rb').read())
Lambda - Python3.8
import io, base64
body = event["body"]
attachment = base64.b64decode(body.encode()) #this is a bytes object
buff = io.BytesIO(attachment) #this is now useable - read/write etc.
#one-liner
buff = io.BytesIO(base64.b64decode(event["body"].encode()))
Not quite sure why, but for me base64 encoding (even with urlsafe) in the original request corrupted the file and it was no longer recognised as a PDF in Lambda, so the OP's answer didn't work for me.

Getting HTTP POST Error : {"reason":null,"error":"Request JSON object for insert cannot be null."}

I am getting HTTP POST error when I am trying to connect to a Service Now Instance for Change Request Automation using Python. Here is the script I am using with Python 3.4.4
# SNOW CR AUTOMATION SCRIPT
import requests
import json
# put the ip address or dns of your SNOW API in this url
url = 'http://<>/change_request.do?JSONv2&sysparm_action=insert'
data= {
'short_description': '<value>',
'priority': '<value>',
'reason': '<value>',
'u_reason_for_change': '<value>',
'u_business_driver': '<value>',
'u_plan_of_record_id': '<value>'
}
print ("Data Inserted :")
print (data)
#Content type must be included in the header
header = {"Authorization":"Basic V1NfRVRPX1ROOkBiY2RlNTQzMjE=","Content- Type":"application/json"}
#Performs a POST on the specified url.
response = requests.request('POST', url, auth=("<value>","<value>"), json=data, headers=header)
print ( " Header is : ")
print (response.headers)
print (" ")
print ( "HTTP Response is :" )
print (response)
print (" ")
print ("***********************")
print (" Output : ")
print ( response.text)
I am getting an error as below while running the above script.
Output :
{"reason":null,"error":"Request JSON object for insert cannot be null."}
I am not sure why this error is thrown. Can anybody please help on this ?
This is a working example I tested on my instance. I am using REST Table API to insert a change request. It's not true that it can not be http. It's whatever protocol your instance allows to connect, say from browser.
#Need to install requests package for python
#easy_install requests
import requests
# Set the request parameters
url = '<yourinstance base url>/api/now/table/change_request'
user = <username>
pwd = <password>
# Set proper headers
headers = {"Content-Type":"application/json","Accept":"application/json"}
# Do the HTTP request
response = requests.post(url, auth=(user, pwd), headers=headers ,data="{\"short_description\":\"test in python\"}")
# Check for HTTP codes other than 201
if response.status_code != 201:
print('Status:', response.status_code, 'Headers:', response.headers, 'Error Response:',response.json())
exit()
# Decode the JSON response into a dictionary and use the data
data = response.json()
print(data)
I think you should use SSL, so no http!
First error I see in your script is how you pass your payload, you need to transform your dictionary into a JSON Object/String. And you don't need to authenticate twice, you have the basic http authentication handled by requests.post so no need for it in the header.
With this script it should work:
import json
import requests
url = 'https://instancename.service-now.com/change_request.do?JSONv2'
user = 'admin'
pwd = 'admin'
# Set proper headers
headers = {"Content-Type":"application/json","Accept":"application/json"}
payload = {
'sysparm_action': 'insert',
'short_description': 'test_jsonv2',
'priority': '1'
}
# Do the HTTP request
response = requests.post(url, auth=(user, pwd), headers=headers, data=json.dumps(payload))
# Check for HTTP codes other than 200
if response.status_code != 200:
print('Status:', response.status_code, 'Headers:', response.headers, 'Error Response:',response.json())
exit()
# Decode the JSON response into a dictionary and use the data
data = response.json()
print(data)

Converting urllib2 POST to Requests

I have an existing Http POST using urllib2:
data = 'client_id=%s&client_secret=%s&grant_type=authorization_code&code=%s&redirect_uri=%s' % (settings.GOOGLE_CLIENT_ID, settings.GOOGLE_CLIENT_SECRET, code, redirect_uri)
req = urllib2.Request(access_token_url, data=data)
response = urllib2.urlopen(req)
response_content = response.read()
json_response = json.loads(response_content)
I'm trying to convert this to the Requests library instead (http://docs.python-requests.org/) but I'm getting a 400 Invalid Request.
Here's my attempt:
params = {'redirect_uri' : redirect_uri}
params['client_id'] = settings.GOOGLE_CLIENT_ID
params['client_secret'] = settings.GOOGLE_CLIENT_SECRET
params['grant_type'] = 'authorization_code'
params['code'] = code
req = requests.post(access_token_url, data=params)
json_response = req.json()
I tried tweaking it to use params instead of data but I got the same error.
Anything I'm missing?
Make sure the values of the data dict are not already escaped as requests will do that for you. Please notice how your original example does not do any escaping.

Categories

Resources