How can I make a Post Request on Python with urllib3? - python

I've been trying to make a request to an API, I have to pass the following body:
{
"description":"Tenaris",
"ticker":"TS.BA",
"industry":"Metalúrgica",
"currency":"ARS"
}
Altough the code seems to be right and it finished with "Process finished with exit code 0", it's not working well. I have no idea of what I'm missing but this is my code:
http = urllib3.PoolManager()
http.urlopen('POST', 'http://localhost:8080/assets', headers={'Content-Type':'application/json'},
data={
"description":"Tenaris",
"ticker":"TS.BA",
"industry":"Metalúrgica",
"currency":"ARS"
})
By the way, this the first day working with Python so excuse me if I'm not specific enough.

Since you're trying to pass in a JSON request, you'll need to encode the body as JSON and pass it in with the body field.
For your example, you want to do something like:
import json
encoded_body = json.dumps({
"description": "Tenaris",
"ticker": "TS.BA",
"industry": "Metalúrgica",
"currency": "ARS",
})
http = urllib3.PoolManager()
r = http.request('POST', 'http://localhost:8080/assets',
headers={'Content-Type': 'application/json'},
body=encoded_body)
print r.read() # Do something with the response?
Edit: My original answer was wrong. Updated it to encode the JSON. Also, related question: How do I pass raw POST data into urllib3?

I ran into this issue when making a call to Gitlab CI. Since the above did not work for me (gave me some kind of error about not being able to concatenate bytes to a string), and because the arguments I was attempting to pass were nested, I thought I would post what ended up working for me:
API_ENDPOINT = "https://gitlab.com/api/v4/projects/{}/pipeline".format(GITLAB_PROJECT_ID)
API_TOKEN = "SomeToken"
data = {
"ref": ref,
"variables": [
{
"key": "ENVIRONMENT",
"value": some_env
},
{ "key": "S3BUCKET",
"value": some_bucket
},
]
}
req_headers = {
'Content-Type': 'application/json',
'PRIVATE-TOKEN': API_TOKEN,
}
http = urllib3.PoolManager()
encoded_data = json.dumps(data).encode('utf-8')
r = http.request('POST', API_ENDPOINT,
headers=req_headers,
body=encoded_data)
resp_body = r.data.decode('utf-8')
resp_dict = json.loads(r.data.decode('utf-8'))
logger.info('Response Code: {}'.format(r.status))
logger.info('Response Body: {}'.format(resp_body))
if 'message' in resp_body:
logfile_msg = 'Failed Gitlab Response-- {} {message}'.format(r.status, **resp_dict)

I recently became interested in using urllib3, and came across this problem. If you read the urllib3 "User Guide" page, you will see this:
For POST and PUT requests, you need to manually encode query parameters in the URL
Your code should be adjusted to look like this:
import urllib3
from urllib.parse import urlencode
data = {"description":"Tenaris",
"ticker":"TS.BA",
"industry":"Metalúrgica",
"currency":"ARS"}
http = urllib3.PoolManager()
encoded_data = urlencode(data)
http.request('POST',
'http://localhost:8080/assets?'+encoded_data,
headers={'Content-Type':'application/json'})

Related

Data is not being POSTed in python. No errors given by compiler

I'm trying to POST data to an api, after execution the compiler does not give any errors, but the data is not showing in the database.
import requests
endpoint = "http://192.168.10.2:8085/api/customer"
myObj = {"customer_id": 900,
"customer_code": "qwertyuiop",
"ustomer_name": "lion",
"contact": "030190000",
"address": "lane"}
x = requests.post(url = endpoint, data = myObj)
Edit:
when I try to do
print(x.text)
I get this error:
{"type":"https://tools.ietf.org/html/rfc7231#section-6.5.13","title":"Unsupported Media Type","status":415,"traceId":"00-9b47b6c7ce1f14499652ba95b3faca3a-cc8e04f53a002647-00"}
Any help would be appreciated.
I found the problem, I needed to use json (which takes a dictionary) instead of data (which takes a string).
import json
import requests
payload = {"customer_id": 456, "customer_code": "fakhr", "customer_name": "fakhr", "contact": "fakhr", "address": "fakhr"}
r = requests.post("http://192.168.10.2:8085/api/customer", json=payload)
print(r.text)

Parse JSON nested data from Requests POST response

I'm working on a project using Python(3.7) in which I have to parse a JSON returned from the POST request using Requests library.
I googled a lot and tried too many solutions but nothing helped me, so
don't mark this as duplicate, please!
Here's what I have tried:
def process_req(payload):
try:
headers = {
'Content-Type': 'application/json'
}
data = payload
resp = requests.post(
'http://<EXAMPLE_URL>',
data=data,
headers=headers
)
print('returned data: {}'.format(resp.content.decode('utf8').replace("'", '"')))
resp = resp.content.decode('utf8').replace("'", '"')
When I print the resp it provide the following JSON:
{
"code": "00",
"message": "Successful",
"data": "{\"requestId\":\"0012602\",\"responseCode\":\"68\",\"responseDescription\":\"Invalid Institution Code\"}"
}
Now, I need to access the data field of that JSON, here what I tried:
resp['data']
But it returns an error as:
string indices must be integers
You're retrieving the data as raw bytes by using resp.content.
Try resp.json() instead. This will decode the JSON into Python objects.

Alpha Vantage API Key returns invalid error in Python, and what is Response[200]?

Using the following code, I am not getting any data from alphavantage, I get the following API error:
"Error Message": "Invalid API call. Please retry or visit the documentation (https://www.alphavantage.co/documentation/) for TIME_SERIES_DAILY." }
import requests
import alpha_vantage
API_URL = "https://www.alphavantage.co/query"
data = {
"function": "TIME_SERIES_DAILY",
"symbol": "NIFTY",
"outputsize": "compact",
"datatype": "csv",
"apikey": "xxx",
}
response = requests.get(API_URL, params=data)
print(response.json())
I edited the code to try something else, but I still got something strange, this time it was:
Response [200]
Here is the code for that:
import requests
import alpha_vantage
API_URL = "https://www.alphavantage.co/query"
data = {
"function": "TIME_SERIES_DAILY",
"symbol": "US",
"outputsize": "compact",
"datatype": "csv",
"apikey": "xxx"
}
response = requests.get(API_URL, params=data)
print(response)
What going on here?
(Key obfuscated below to xxx)
There are three issues going on with your attempts to call this API.
In your first attempt, you correctly call the API but use an invalid ticker. NIFTY along with other global indexes are not supported by the Alpha Vantage API.
On your second attempt, you print out a response object, which when converted to string looks just like the output you received, Response[200] meaning a successful API call was made. To get the data from it, you have to print response.text or response.json()
The third issue is more subtle, and depends on what you are trying to return. If you want to return a csv file using the datatype: "csv", you cannot use response.json() since the format isn't for json. You can instead use the default datatype: "json", by leaving that field blank.
If you want to get a csv file, you can use print(response.text)
JSON example
import requests
import alpha_vantage
API_URL = "https://www.alphavantage.co/query"
data = {
"function": "TIME_SERIES_DAILY",
"symbol": "M&M.NSE",
"outputsize": "compact",
"apikey": "xxx"
}
response = requests.get(API_URL, params=data)
print(response.json())
CSV example
import requests
import alpha_vantage
API_URL = "https://www.alphavantage.co/query"
data = {
"function": "TIME_SERIES_DAILY",
"symbol": "M&M.NSE",
"outputsize": "compact",
"datatype": "csv",
"apikey": "xxx"
}
response = requests.get(API_URL, params=data)
print(response.text)

logging into the MATCHBOOK API with Python Requests

I am trying (legitimately and with the go ahead from the site)to log into the betting exchange matchbook.com through their api.
The documentation states:
To Login: https://www.matchbook.com/bpapi/rest/security/session
and
Example Request
POST /security/session
{
"username": "j_henry",
"password": "******"
}
Example Response
{
"session-token": "1418_1234567890",
"user-id": 1418,
"account": { // Same as GET /account API response.
...
}
}
I am using Requests and have the following code:
payload = {"username": "********", "password": "************"}
r = requests.post('https://www.matchbook.com/edge/rest/security/session', data=payload)
print (r.status_code)
I get error code 415? I must be getting the wrong type of response??
I have looked at a lot of very similar posts on here, and I am about to ask matchbook's team, but before I do has anybody got any ideas?
You might have to specify Content-Type, try to add a header to tell the server it's JSON formatted:
payload = {"username": "********", "password": "************"}
headers = {"Content-Type": "application/json;"}
r = requests.post('https://www.matchbook.com/edge/rest/security/session', data=payload, headers=headers)
print (r.status_code)
It does not appear from your code that you are JSON-encoding your payload. The endpoint is likely expecting JSON.
Try this:
payload = '{"username": "********", "password": "************"}'

post request to change permissions for a file in google drive is failing

Im using python requests library to make google a drive api request to change permissions of a file, in this case the owner.
Here is what my code looks like
fileId = "123abcEfJl-mNooP45Kl6u" #fake file id
url = https://www.googleapis.com/drive/v2/files/%s/permissions' % fileId
payload = {"role":"owner", "type":"user", "value":"<some_user>#gmail.com"}
headers = {'Authorization': 'Bearer %s'%access_token, 'Content-Type':'application/json'}
permResponse = requests.post(url, data=payload, headers=headers)
print permResponse.text
When I run this, I get the following response:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "parseError",
"message": "Parse Error"
}
],
"code": 400,
"message": "Parse Error"
}
}
I've been following the google docs api for this and have not been able to figure out what im doing incorrectly.
https://developers.google.com/drive/v2/reference/permissions/insert
Even their Try It! section is broken because there isn't an option to add the required 'value' field.
What am I doing incorrectly? Is anyone else running into these issues?
Thanks
I'm using the urllib.request module, and It works fine. This is my code:
key = "?key=" + MY_API_KEY
url_destino = ("https://www.googleapis.com/drive/v2/files/%s/permissions" % source_id)+ key
values = "{"role":"owner", "type":"user", "value":"<some_user>#gmail.com"}"
data = values.encode('utf-8')
request = urllib.request.Request(url_destino, data, method='POST')
request.add_header("Authorization", "Bearer " + token)
request.add_header("Content-Length", len(data))
request.add_header("Content-Type", "application/json")
print(request.header_items()) # for debugging purpouse
f = urllib.request.urlopen(request)
print(f.read())
I've thought to replace the urllib.request by Requests module (it's more clean to work with) in my little library but, now works.
Because I use Python 3 I can't use the google-api-python-client.

Categories