Using Python to test HTTP APIs - python

I'm fairly new to Python programming and I don't know all the libraries needed for the following.
I would like to use Python to test some HTTP APIs. Mainly I want to use OAuth and make a few JSON calls. The APIs in question can be found on: https://developers.trustpilot.com/authentication and the generate product review link (I can only use one link)
I want to authenticate myself and then generate a product review link in one step. So far I've been using the Advanced REST client (ARC) to make these calls individually. I could also use .arc files if you think it's easier.
The idea would be make these calls successively in one go. So it would be something along the lines:
1) Make the authentication call.
The HTTP Method looks like this:
https://api.trustpilot.com/v1/oauth/oauth-business-users-for-applications/accesstoken
Method Post:
Header
Authorization: Basic Base64encode(APIkey:Secret)
Content-Type: application/x-www-form-urlencoded
Payload:
grant_type=password&username=user#mail.com&password=SomePass
Translate this bit into Python basically.
1.a) Add a header to the call
Header Authorization: base64encode hash Content-Type: application/x-www-form-urlencoded
1.b) Add a payload to the call
Payload: grant_type=password&username
4) Receive the token from call made in step 1) (Result is format)
"access token": Auth_token
5) Take the token and use it in creating a product review.
5.a) Add the token in the header
Header: Authorization: Bearer Auth_token
6.a) Add a JSON payload to the call made in step 5.
Here's the code I have so far:
Import requests
header = {'Authorization: Basic NnNrQUprTWRHTU5VSXJGYXBVRGxack1oT01oTUFRZHI6QTFvOGJjRUNDdUxBTmVqUQ==}','Content-Type: application/x-www-form-urlencoded'}
payload = {'grant_type=password&username=email#address.com&password=SomePassword'}
r = requests.post('https://api.trustpilot.com/v1/oauth/oauth-business-users-for-applications/accesstoken', headers=header, params=payload )
Ideally I want to create the requests.post(url, header, payload) and then return what the server answers in JSON format. I think that print r.text would do the last part.
So this is the code I have writtent (that works now):
import requests
import getpass
import json
from requests.auth import HTTPBasicAuth
header = {'grant_type':'password' , 'username':'mail#maildomain.com', 'password':'YourPassword'}
username= "YOURAPIKEY" #APIKey
password= "YOURSECRET" #Secret
res = requests.post(
'URL/v1/oauth/oauth-business-users-for-applications/accesstoken',
auth=HTTPBasicAuth(username, password), # basic authentication
data=header)
#print(res.content) #See content of the call result.
data = res.json() # get response as parsed json (will return a dict)
auth_token = data.get('access_token')

requests can do all what you ask without any work from your part.
See the doc for authentication, parameters, json output, json input
Make the authentication call.
import requests
import getpass
from requests.auth import HTTPBasicAuth
username = raw_input('Username: ')
password = getpass.getpass('Password: ')
res = requests.post(
'https://api.trustpilot.com/v1/oauth/oauth-business-users-for-applications/accesstoken',
auth=HTTPBasicAuth(username, password), # basic authentication
params={ # url parameters
'grant_type': 'password',
'username': 'email#address.com',
'password': 'SomePassword'
})
Receive the token from call made in step 1) (Result is format)
# res = requests.post.....
data = res.json() # get response as parsed json (will return a dict)
auth_token = data.get('access token')
Take the token and use it in creating a product review.
request.post(
'.../product_review',
headers={
'Authorization': 'Bearer ' + auth_token
},
json={'my': 'payload'}) # send data as json

Related

Problem sending post requests to spotify api in python

def queue_song(session_id):
song_uri='spotify:track:5RwV8BvLfX5injfqYodke9'
tokens = get_user_tokens(session_id)
headers = {'Content-Type': 'application/json',
'Authorization': "Bearer " + tokens.access_token,
}
url = BASE_URL +'player/queue'
data={
'uri':song_uri
}
response = requests.post(url,headers=headers,data=data).json()
print(response)
Output:
{'error': {'status': 400, 'message': 'Required parameter uri missing'}}
https://developer.spotify.com/documentation/web-api/reference/#/operations/add-to-queue
I dont thing there is any problem with auth tokens... coz 'GET' requests are working fine
By default, using data= in requests.post() sets the content type to application/x-www-form-urlencoded which makes the body a akin to a HTTP form request.
Spotify's API is JSON based, so your data needs to be a valid json data.
You can do it in 2 ways:
response = requests.post(url,headers=headers,data=json.dumps(data)).json()
Or, more simply:
response = requests.post(url,headers=headers,json=data).json()
and in this way you don't need to manually set the application/json header as well.
Edit:
After going through the API docs you linked, there's more wrong with the call you're making.
You're sending the parameters in data - which is the body of the request. But Spotify API specifies the parameters need to be put in the Query i.e. the query string of the URI. Which means your request should be:
response = requests.post(url,headers=headers,params=data).json() # set query string not body

Http Basic Auth with RFC2045-MIME variant of Base64 in python

I am currently working with and API that requires "RFC2045-MIME variant of Base64, except not limited to 76 char/line" this seems to be different from the normal basic auth used in the requests library. Curious if anyone else has come across this and been able to solve it? I imagine I will have to write a function to do this encoding and build the header manually.
Yes, you can create a function as shown below where the headers for the request are created manually.
For this implementation, you will need these variables:
API_PUBLIC_KEY,
API_SECRET_KEY,
host_url,
endpoint (where the API is supposed to hit).
import base64
import requests
def create_request():
auth_header = base64.b64encode(bytes(f'{API_PUBLIC_KEY}:{API_SECRET_KEY}'.encode('ascii'))).decode('utf-8')
headers = {
'Host': host_url,
'Authorization': f'Basic {auth_header}',
'Content-Type': 'application/json'
}
api_endpoint = f'https://{host_url}/{endpoint}'
data = {}
response = requests.request("POST", api_endpoint, headers=headers, data=data)
print(response.text.encode('utf8'))

API access to trading platform using Python

I'm new to getting data using API and Python. I want to pull data from my trading platform. They've provided the following instructions:
http://www.questrade.com/api/documentation/getting-started
I'm ok up to step 4 and have an access token. I need help with step 5. How do I translate this request:
GET /v1/accounts HTTP/1.1
Host: https://api01.iq.questrade.com
Authorization: Bearer C3lTUKuNQrAAmSD/TPjuV/HI7aNrAwDp
into Python code? I've tried
import requests
r = requests.get('https://api01.iq.questrade.com/v1/accounts', headers={'Authorization': 'access_token myToken'})
I tried that after reading this: python request with authentication (access_token)
Any help would be appreciated. Thanks.
As you point out, after step 4 you should have received an access token as follows:
{
“access_token”: ”C3lTUKuNQrAAmSD/TPjuV/HI7aNrAwDp”,
“token_type”: ”Bearer”,
“expires_in”: 300,
“refresh_token”: ”aSBe7wAAdx88QTbwut0tiu3SYic3ox8F”,
“api_server”: ”https://api01.iq.questrade.com”
}
To make subsequent API calls, you will need to construct your URI as follows:
uri = [api_server]/v1/[rest_operation]
e.g.
uri = "https://api01.iq.questrade.com/v1/time"
Note: Make sure you use the same [api_server] that you received in your json object from step 4, otherwise your calls will not work with the given access_token
Next, construct your headers as follows:
headers = {'Authorization': [token_type] + ' ' + [access_token]}
e.g.
headers = {'Authorization': 'Bearer C3lTUKuNQrAAmSD/TPjuV/HI7aNrAwDp'}
Finally, make your requests call as follows
r = requests.get(uri, headers=headers)
response = r.json()
Hope this helps!
Note: You can find a Questrade API Python wrapper on GitHub which handles all of the above for you.
https://github.com/pcinat/QuestradeAPI_PythonWrapper
Improving a bit on Peter's reply (Thank you Peter!)
start by using the token you got from the QT website to obtain an access_token and get an api_server assigned to handle your requests.
# replace XXXXXXXX with the token given to you in your questrade account
import requests
r = requests.get('https://login.questrade.com/oauth2/token?grant_type=refresh_token&refresh_token=XXXXXXXX')
access_token = str(r.json()['access_token'])
refresh_token= str(r.json()['refresh_token']) # you will need this refresh_token to obtain another access_token when it expires
api_server= str(r.json()['api_server'])
token_type= str(r.json()['token_type'])
api_server= str(r.json()['api_server'])
expires_in = str(r.json()['expires_in'])
# uri = api_server+'v1/'+[action] - let's try checking the server's time:
uri = api_server+'v1/'+'time'
headers = {'Authorization': token_type +' '+access_token}
# will look sth like this
# headers will look sth like {'Authorization': 'Bearer ix7rAhcXx83judEVUa8egpK2JqhPD2_z0'}
# uri will look sth like 'https://api05.iq.questrade.com/v1/time'
# you can test now with
r = requests.get(uri, headers=headers)
response = r.json()
print(response)

Python requests parameters not going through

I'm trying to make a post request to Quizlet following their OAuth flow from these instructions https://quizlet.com/api/2.0/docs/authorization-code-flow. I'm running into a problem where on Step 2, I have to make a post request with a token I generated from their server, but I'm not having success passing in the token to the url. I know it was generated correctly, but I'm having trouble passing it in and not getting a 400 response.
More directly, my question is, is there another way of including the grant_type and code parameters that I'm trying to pass in through the url in the post request such as passing them in through the header of the post request? I've looked at the documentation for requests but I've had no luck.
#app.route('/')
#app.route('/index')
def index():
code = request.args.get('code')
state = request.args.get('state')
print("code is " + code)
r = requests.post("https://api.quizlet.com/oauth/token?grant_type=authorization_code&code=" + code)
return render_template('index.html')
You must specify the required headers Authorization, Content-Type.
import requests
from requests.auth import _basic_auth_str
client_id = 'YOUR CLIENT ID'
secret = 'YOUR CLIENT SECRET'
code = 'CODE FROM STEP 1'
headers = {
'Authorization': _basic_auth_str(client_id, secret),
'Content-Type': 'application/x-www-form-urlencoded'
}
r = requests.post('https://api.quizlet.com/oauth/token?grant_type=authorization_code&code={0}'.format(
code), headers=headers)
print r.status_code
print r.content

Python requests library how to pass Authorization header with single token

I have a request URI and a token. If I use:
curl -s "<MY_URI>" -H "Authorization: TOK:<MY_TOKEN>"
etc., I get a 200 and view the corresponding JSON data.
So, I installed requests and when I attempt to access this resource I get a 403 probably because I do not know the correct syntax to pass that token. Can anyone help me figure it out?
This is what I have:
import sys,socket
import requests
r = requests.get('<MY_URI>','<MY_TOKEN>')
r. status_code
I already tried:
r = requests.get('<MY_URI>',auth=('<MY_TOKEN>'))
r = requests.get('<MY_URI>',auth=('TOK','<MY_TOKEN>'))
r = requests.get('<MY_URI>',headers=('Authorization: TOK:<MY_TOKEN>'))
But none of these work.
In python:
('<MY_TOKEN>')
is equivalent to
'<MY_TOKEN>'
And requests interprets
('TOK', '<MY_TOKEN>')
As you wanting requests to use Basic Authentication and craft an authorization header like so:
'VE9LOjxNWV9UT0tFTj4K'
Which is the base64 representation of 'TOK:<MY_TOKEN>'
To pass your own header you pass in a dictionary like so:
r = requests.get('<MY_URI>', headers={'Authorization': 'TOK:<MY_TOKEN>'})
I was looking for something similar and came across this. It looks like in the first option you mentioned
r = requests.get('<MY_URI>', auth=('<MY_TOKEN>'))
"auth" takes two parameters: username and password, so the actual statement should be
r=requests.get('<MY_URI>', auth=('<YOUR_USERNAME>', '<YOUR_PASSWORD>'))
In my case, there was no password, so I left the second parameter in auth field empty as shown below:
r=requests.get('<MY_URI', auth=('MY_USERNAME', ''))
Hope this helps somebody :)
This worked for me:
access_token = #yourAccessTokenHere#
result = requests.post(url,
headers={'Content-Type':'application/json',
'Authorization': 'Bearer {}'.format(access_token)})
You can also set headers for the entire session:
TOKEN = 'abcd0123'
HEADERS = {'Authorization': 'token {}'.format(TOKEN)}
with requests.Session() as s:
s.headers.update(HEADERS)
resp = s.get('http://example.com/')
I found it here, it's working for me with Linkedin:
https://auth0.com/docs/flows/guides/auth-code/call-api-auth-code
The code I used with Linkedin login is:
ref = 'https://api.linkedin.com/v2/me'
headers = {"content-type": "application/json; charset=UTF-8",'Authorization':'Bearer {}'.format(access_token)}
Linkedin_user_info = requests.get(ref1, headers=headers).json()
Requests natively supports basic auth only with user-pass params, not with tokens.
You could, if you wanted, add the following class to have requests support token based basic authentication:
import requests
from base64 import b64encode
class BasicAuthToken(requests.auth.AuthBase):
def __init__(self, token):
self.token = token
def __call__(self, r):
authstr = 'Basic ' + b64encode(('token:' + self.token).encode('utf-8')).decode('utf-8')
r.headers['Authorization'] = authstr
return r
Then, to use it run the following request :
r = requests.get(url, auth=BasicAuthToken(api_token))
An alternative would be to formulate a custom header instead, just as was suggested by other users here.
You can try something like this
r = requests.get(ENDPOINT, params=params, headers={'Authorization': 'Basic %s' % API_KEY})
This worked for me:
r = requests.get('http://127.0.0.1:8000/api/ray/musics/', headers={'Authorization': 'Token 22ec0cc4207ebead1f51dea06ff149342082b190'})
My code uses user generated token.
You have a request needing an authorization maybe you have a result 401.
Suppose your request is like this :
REQ ='https://api.asite.com/something/else/else'
You have your token :
TOKEN = 'fliuzabuvdgfnsuczkncsq12454632'
build your header like this :
HEADER = {'Authorization': f'{TOKEN}'}
and use it like this :
req.get(REQ, headers=HEADER)
display your result like this :
req.get(COACH, headers=HEADER).json()

Categories

Resources