curl to python requests conversion - python

I'm working with Dropbox's python API, trying to convert the following curl command to Python Requests:
curl -X POST https://content.dropboxapi.com/2/files/download \
--header "Authorization: Bearer <ACCESS_TOKEN>" \
--header "Dropbox-API-Arg: {\"path\": \"/Homework/math/Prime_Numbers.txt\"}"
My translation so far:
downloadHeader={"Authorization: " + authorization}
downloadURL = "https://content.dropboxapi.com/2/files/download"
downloadPayload = {"Dropbox-API-Arg": {"path": "/" + dbPATH}}
downloadResponse = requests.post(downloadURL, data=json.dumps(downloadPayload), headers=downloadHeader)
However, when I run this I get the following error:
for header in headers.items():
AttributeError: 'set' object has no attribute 'items'
Can anyone give me some feedback? I'm confident about my authorization value because it's working in a separate request which I'm copy and pasting below:
MDlink = "https://api.dropboxapi.com/2/sharing/get_shared_link_metadata"
authorization = "Bearer " + ACCESS_TOKEN
headers={"Content-Type":"application/json", "Authorization": authorization}
payload = {"url": imageLink}
response = requests.request("POST", MDlink, data=json.dumps(payload), headers=headers)
Thank you very much!

You want this
downloadHeader={"Authorization: " + authorization}
To be
downloadHeader={"Authorization": authorization}
Or more precisely
downloadHeader={"Authorization": "Bearer <ACCESS_TOKEN>"}
Explanation:
{1} # this is a set. It has no .items()
{1: 1} # this is a dict. You can call .items()

Related

Python deleting a repo from github with request module

I do not coding a this situation.
I can create a repository in python using a request.post(), but I can not delete a this repository.
Here is the code:
def deleteRepository(self, repo, name):
headers = {'Accept': 'application/vnd.github.v3+json',
'Authorization': 'token {}'.format(self.token)}
response = requests.delete(self.api_url + '/repos/' + name + repo, headers = headers)
return response.json()
+ name + repo seems strange.
Consider this implementation for instance
def deleteRepository(self,name,username):
response = requests.delete(self.api_url+'/repos/' + username + '/'+name+'?access_token='+self.token)
print(response.status_code)
Note the '/repos/' + username + '/'+name+' part: separators are important for your path segments.
Update June 2021: as explained in "
Deprecating API authentication through query parameters "
If you're currently making an API call similar to
curl "https://api.github.com/user/repos?access_token=my_access_token"
Instead, you should send the token in the header:
curl -H 'Authorization: token my_access_token' https://api.github.com/user/repos
So:
def deleteRepository(self,name,username):
response = requests.delete(self.api_url+'/repos/' + username + '/'+name+', headers={'Authorization': 'token self.token'})
print(response.status_code)

Connecting to oauth2 API - it works with curl, doesn't with requests.get (Python)

I've been trying to connect to an oauth2 API. I've managed to write a code that delivers a token, so the token is not a problem.
I've checked that with curl. The following works:
curl -X GET \
https://api.website.pl/sale/delivery-methods \
-H 'Authorization: Bearer eyJhbGciOiJSUzBmF1BWKBjk3GiA' \
-H 'accept: application/vnd.website.public.v1+json'
<- This returns the data I need.
However, I simply can't make it work in python.
headers = {}
headers['Authorization'] = 'Bearer eyJhbGciOiJSUzBmF1BWKBjk3GiA'
headers['Accept'] = 'application/vnd.website.public.v1+json'
get_url = 'https://api.website.pl/sale/delivery-methods'
requests.get(get_url, headers)
The response is <Response [406]>, incorrect data, which I'm interpreting as a signal I didn't pass all the relevant authorization headers.
Any ideas how to fix that?
try this:
headers = {}
headers['Authorization'] = 'Bearer eyJhbGciOiJSUzBmF1BWKBjk3GiA'
headers['Accept'] = 'application/vnd.website.public.v1+json'
get_url = 'https://api.website.pl/sale/delivery-methods'
response = requests.get(get_url, headers=headers)

HTTP Error 422: Unprocessable Entity - when calling API from Python (but curl works)

When trying out the digitalocean v2 api I come across the following behaviour:
curl -X POST "https://api.digitalocean.com/v2/droplets" \
-d'{"name":"t002","region":"ams3","size":"512mb","image":"debian-7-0-x64","ssh_keys":[123]}' \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json"
Works fine and the droplet gets created.
Now when I do call it from python with:
json_values = {'name': 's002', 'region': 'ams3', 'size': '512mb', 'image': 'debian-7-0-x64', 'ssh_keys': [123]}
data = urllib.parse.urlencode(json_values)
data = data.encode("utf-8")
try:
req = urllib.request.Request(create_droplets_url, data)
req.add_header("User-Agent", uagent) # set custom user agent
req.add_header("Authorization", BearerToken) # set custom user agent
response = urllib.request.urlopen(req)
I get back: HTTP Error 422: Unprocessable Entity with no further information. Am i doing something wrong on the python side? Thx
Additional Info:
I figured out that the problem must be with ssh_keys. If I remove that element everything works fine.
Why are you url-encoding the data? That's not what the curl version is doing. Dump it to JSON instead:
data = json.dumps(json_values)
req = urllib.request.Request(create_droplets_url, data)
I have received the same error and realized it has occurred due to the server side validation failed with your post data.
Solution:
use requests.post instead of urllib.request.Request then you could get the accurate error message for that serverside 422 error code.
Sample code:
import requests
API_URL = "***"
TOKEN = "***"
HEADERS = {
"User-Agent": "Python API Sample",
"Authorization": "Bearer " + TOKEN,
"Content-Type": "application/json"
}
data = {
"user_id": "***",
"project_id": "***"
}
json_data = json.dumps(data).encode('utf8')
response = requests.post(url=API_URL, headers=HEADERS, data=json_data)
print(json.dumps(json.loads(response.text), sort_keys=True, indent=4, separators=(",", ": ")))
Thanks :)

how to implement CURL cli using python to consume REST services

There are lot of questions posted how to consume the REST services with python, but none of them worked for me,
currently with the below curl cli i can get the authentication token.
curl cli
curl -v --user username:pass1234 -H "content-type: application/json" -X POST -d "" https://mywebsite/api/v1/auth/token-services --insecure
when i execute the above cli i get the json response as below :
output snip from above curl cli
< HTTP/1.1 200 OK
< Server: nginx/1.4.2
< Date: Mon, 14 Apr 2014 23:22:41 GMT
< Content-Type: application/json
< Content-Length: 201
< Connection: keep-alive
Connection #0 to host <ipaddress> left intact
* Closing connection #0
* SSLv3, TLS alert, Client hello (1):
{"kind": "object#auth-token", "expiry-time": "Mon Apr 14 23:37:41 2014", "token-id": "l3CvWcEr5rKvooOaCymFvy2qp3cY18XCs4JrW4EvPww=", "link": "https://mywebsite/api/v1/auth/token-services/1634484805"}
NOW MY QUESTION is, how to achieve this using python. WHAT libraries i should use? i need to extract the token-id from the json response. so that i will use that token for further request to consume REST services.
if some one can post the PYTHON code snippet for this that would be great.
Have a look at the following HOWTO of the python documentation: HOWTO Fetch Internet Resources Using urllib2. There you also find a section with an code example for Basic authentication. The HOWTO describes how you can use the module urllib2.
Other useful libraries:
requests
mechanize
I got the solution for what i am looking for...
Complete Sample code ...
import requests
from requests.auth import HTTPBasicAuth
import json
token = ""
def get_token(username, password, url):
global token
#verify=False will not verify the ssl
resp = requests.post(url, auth=HTTPBasicAuth(username, password), verify=False)
print "\n", dir(resp)
print "Status Code:", resp.status_code, "\n"
print "text:", resp.text, "\n"
print "json:", resp.json(), "\n"
print "Content:", resp.content, "\n"
print "Headers:", resp.headers, "\n"
print "Header(Content-type:)", resp.headers.get('content-type'), "\n"
print "Header(Content-length:)", resp.headers.get('content-length'), "\n"
print "OK:", resp.ok, "\n"
print "json dump:", json.dumps(resp.json())
json_dict = json.loads(resp.text)
token = json_dict['token-id']
print "\ntoken-id:", json_dict['token-id']
for key, value in json_dict.items():
print key, "=>", value
return token
def get_global_users(token):
print "\nexecuting get_global_users.."
print "Token", token
url = 'https://xxx.xxx.xxx.xxx/api/v1/global/users'
headers_dict = {'content-type': 'application/json', 'Accept': 'application/json', 'X-Auth-Token': token}
resp = requests.get(url, headers=headers_dict, verify=False)
print "Status Code:", resp.status_code, "\n"
print "text:", resp.text, "\n"
print "json:", resp.json(), "\n"
json_users = json.loads(resp.text)
print "all users:\n", json_users['users']
print "\n"
for users in json_users['users']:
for key, value in users.items():
print key, "=>", value
def post_global_user(token):
print "\nexecuting post_global_users.."
print "Token:", token
url = 'https://xxx.xxx.xxx.xxx/api/v1/global/users'
headers_dict = {'content-type': 'application/json', 'Accept': 'application/json', 'X-Auth-Token': token}
payload = {'username': 'myuser', 'password': 'pas1234', 'pw-type': 0, 'privilege': 15}
resp = requests.post(url, data=json.dumps(payload), headers=headers_dict, verify=False)
print "Status Code:", resp.status_code, "\n"
To emulate the curl command:
$ curl -v --user username:pass1234 -H "accept: application/json" \
-X POST -d "" https://mywebsite/api/v1/auth/token-services --insecure
in Python using only stdlib:
#!/usr/bin/env python
import base64
import json
from urllib2 import urlopen, Request
credentials = base64.b64encode(b'username:pass1234')
headers={'Authorization': b'Basic ' + credentials,
'Accept': 'application/json'}
response = urlopen(Request("https://example.com/post", b"", headers))
data = json.load(response)
token_id = data["token-id"]
If you want to see what is sent to/received from a server for https requests; enable debugging:
import urllib2
urllib2.install_opener(urllib2.build_opener(urllib2.HTTPSHandler(debuglevel=1)))

Exception Value: HTTP Error 400: Bad Request after a Python/urllib2 request to PayPal Sandbox Site

I'm trying to integrate PayPal REST API in my website. As a first step, I'm trying to translate cURL commands into Python and I'm getting an Exception Value: HTTP Error 400.
The code I'm using (is based on https://stackoverflow.com/a/2003832/2675537):
def basic_authorization(user, password):
s = user + ":" + password
return "Basic " + s.encode("base64").rstrip()
req = urllib2.Request("https://api.sandbox.paypal.com/v1/oauth2/token",
headers = {
"Authorization": basic_authorization("EBWKjlELKMYqRNQ6sYvFo64FtaRLRR5BdHEESmha49TM", "EO422dn3gQLgDbuwqTjzrFgFtaRLRR5BdHEESmha49TM"),
"Accept": "application/json",
"Accept": "*/*",
"User-Agent": "my-python-app/1",
},
data = '{"message":{"body":' + 'grant_type=client_credentials' + '}}' )
f = urllib2.urlopen(req)
return HttpResponse(f)
which is the equivalent (I guess) to:
curl https://api.sandbox.paypal.com/v1/oauth2/token \
-H "Accept: application/json" \
-u "EBWKjlELKMYqRNQ6sYvFo64FtaRLRR5BdHEESmha49TM:EO422dn3gQLgDbuwqTjzrFgFtaRLRR5BdHEESmha49TM" \
-d "grant_type=client_credentials"
And the traceback is here: (Edit: Broken Link)
According to PayPal I should get a response like this:
{"scope":"https://api.paypal.com/v1/payments/.* https://api.paypal.com/v1/vault/credit-card https://api.paypal.com/v1/vault/credit-card/.* https://api.paypal.com/v1/developer/.*","access_token":"OABI8rm75u.5EIuK7.JrI2sLhnv3rhDgLElKAwTfyys","token_type":"Bearer","app_id":"APP-2EJ531395M785864S","expires_in":28800}
Is there an error in my code? Is there a better way to do it?
First of all, I would suggest you not to post your keys in clear text in your code examples.
The error your getting "HTTP Error 400: Bad Request", is due to a badly formed request.
From the docs the format for a request is:
urllib2.Request(url[, data][, headers][, origin_req_host][, unverifiable])
data may be a string specifying additional data to send to the server,
or None if no such data is needed.
headers should be a dictionary, and will be treated as if add_header()
was called with each key and value as arguments.
So your data field is passing a dict instead of string, and it would be a lot more readable
if you separated the fields outside of the Request class. When you have multiple header
fields to fill in, I find it better to use the add_header method as shown below.
import urllib, urllib2
def basic_authorization(user, password):
s = user + ":" + password
return "Basic " + s.encode("base64").rstrip()
url = "https://api.sandbox.paypal.com/v1/oauth2/token"
params = { "grant_type": client_credentials}
data = urllib.urlencode(params)
req = urllib2.Request(url, data)
req.add_header("Authorization",basic_authorization("XXX"))
req.add_header("Accept", "application/json")
req.add_header("User-Agent", "my-python-app/1")
response = urllib2.urlopen(req)

Categories

Resources