5. HTTP using requests

5.1. Basic API

import requests

requests.get('https://httpbin.org/get')                          # <Response [200]>
requests.post('https://httpbin.org/post', data={'key':'value'})  # <Response [200]>
requests.put('https://httpbin.org/put', data={'key':'value'})    # <Response [200]>
requests.delete('https://httpbin.org/delete')                    # <Response [200]>
requests.head('https://httpbin.org/get')                         # <Response [200]>
requests.options('https://httpbin.org/get')                      # <Response [200]>

5.2. Response

from http import HTTPStatus
import requests


response = requests.get('https://httpbin.org/get')
# <Response [200]>

if response.status_code == HTTPStatus.OK:
    data = reponse.raw      # Raw Response Content
    data = reponse.content  # Binary Response Content
    data = response.text    # Response Content
    data = response.json()  # JSON Response Content

    print(data)

5.3. GET Requests

  • params
from http import HTTPStatus
import requests


response = requests.get('https://httpbin.org/get')
# <Response [200]>

if response.status_code == HTTPStatus.OK:
    data = response.json()
    print(data)
from http import HTTPStatus
import requests


params = {'key1': 'value1', 'key2': 'value2'}

response = requests.get('https://httpbin.org/get', params=params)
# <Response [200]>

print(response.url)
# https://httpbin.org/get?key2=value2&key1=value1

if response.status_code == HTTPStatus.OK:
    data = response.json()
    print(data)
from http import HTTPStatus
import requests


data = {'key1': 'value1', 'key2': ['value2', 'value3']}

response = requests.get('https://httpbin.org/get', params=data)
# <Response [200]>

print(response.url)
# https://httpbin.org/get?key1=value1&key2=value2&key2=value3

if response.status_code == HTTPStatus.OK:
    data = response.json()
    print(data)

5.4. POST Requests

5.4.1. POST Request with data

from http import HTTPStatus
import requests


data = {'first_name': 'Jose', 'last_name': 'Jimenez'}

response = requests.post('https://httpbin.org/post', data=data)
# <Response [200]>

if response.status_code == HTTPStatus.OK:
    print('Created')
from http import HTTPStatus
import requests


data = {'key1': ['value1', 'value2']}

response = requests.post('https://httpbin.org/post', data=data)
# <Response [200]>

print(response.text)
# {
#   ...
#   "form": {
#     "key1": [
#       "value1",
#       "value2"
#     ]
#   },
#   ...
# }

if response.status_code == HTTPStatus.OK:
    print('Created')

5.4.2. POST Request with JSON

import json
from http import HTTPStatus
import requests


data = {
    'first_name': 'Jose',
    'last_name': 'Jimenez',
}

response = requests.post('https://httpbin.org/post', data=json.dumps(data))
# <Response [200]>

if response.status_code == HTTPStatus.OK:
    print('Created')
import json
from http import HTTPStatus
import requests


data = {
    'first_name': 'Jose',
    'last_name': 'Jimenez',
}

response = requests.post('https://httpbin.org/post', json=data)
# <Response [200]>

if response.status_code == HTTPStatus.OK:
    print('Created')

5.5. DELETE Requests

import requests
from http import HTTPStatus


response = requests.delete('https://httpbin.org/delete')
# <Response [200]>

if response.status_code == HTTPStatus.OK:
    print('Deleted')

5.6. Custom Headers

import requests
from http import HTTPStatus


headers = {
    'User-Agent': 'Python requests'
}

response = requests.get('https://httpbin.org/post', headers=headers)
# <Response [200]>

if response.status_code == HTTPStatus.OK:
    data = response.json()
    print(data)
response.headers
# {
#     'content-encoding': 'gzip',
#     'transfer-encoding': 'chunked',
#     'connection': 'close',
#     'server': 'nginx/1.0.4',
#     'x-runtime': '148ms',
#     'etag': '"e1ca502697e5c9317743dc078f67693f"',
#     'content-type': 'application/json'
# }
response.headers['Content-Type']
# 'application/json'

response.headers.get('content-type')
# 'application/json'

5.7. Timeout

import requests


requests.get('https://httpbin.org/get', timeout=0.001)
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# requests.exceptions.Timeout: HTTPConnectionPool(host='httpbin.org', port=80): Request timed out. (timeout=0.001)

5.8. Basic Auth

import requests
from http import HTTPStatus


response = requests.get('https://api.github.com/users', auth=('login', 'password'))
# <Response [200]>

if response.status_code == HTTPStatus.OK:
    data = response.json()
    print(data)

5.9. Requests OAuth

pip install requests_oauthlib
Code Listing 5.3. Requests OAuth
from requests_oauthlib import OAuth2Session

from flask import Flask, request, redirect, session, url_for
from flask.json import jsonify

# This information is obtained upon registration of a new GitHub
client_id = "<your client key>"
client_secret = "<your client secret>"
authorization_base_url = 'https://github.com/login/oauth/authorize'
token_url = 'https://github.com/login/oauth/access_token'


@app.route("/login")
def login():
    github = OAuth2Session(client_id)
    authorization_url, state = github.authorization_url(authorization_base_url)

    # State is used to prevent CSRF, keep this for later.
    session['oauth_state'] = state
    return redirect(authorization_url)


@app.route("/callback")
def callback():
    github = OAuth2Session(client_id, state=session['oauth_state'])
    token = github.fetch_token(token_url, client_secret=client_secret,
                               authorization_response=request.url)

    return jsonify(github.get('https://api.github.com/user').json())

5.10. Assignments

5.10.1. REST API

  1. Załóż darmowe konto na Github i potwierdź email
  2. W przeglądarce internetowej wygeneruj w swoim profilu token https://github.com/settings/tokens
  3. Używając biblioteki requests
  4. Zaciągnij informacje o repozytoriach użytkownika Django na https://github.com
  5. Każdy request uwierzytelnij za pomocą Basic Auth i swojego Access Tokena
  6. Następnie z przeglądnij listę z poziomu Pythona i znajdź URL dla repozytorium django
  7. Przeglądnij to repozytorium i jego listę commitów
  8. Podaj datę i opis ostatniego commita
  9. Znajdź numery ID ticketów (Fixed #...) z issue trackera, które zostały rozwiązane w ostatnim miesiącu
About:
  • Filename: requests_github.py
  • Lines of code to write: 35 lines
  • Estimated time of completion: 30 min
The whys and wherefores:
 
  • Komunikacja HTTP (request, response)
  • Parsowanie odpowiedzi HTTP
  • Sprawdzanie stanu połączenia
  • Serializacja i parsowanie JSON
  • Korzystanie z API i dokumentacji
  • Regexpy
  • Używanie biblioteki standardowej i bibliotek zewnętrznych
Hints:
"name": "django",
"full_name": "django/django",

# wyszukaj "commits_url": ???
https://api.github.com/

GET /orgs/django/repos
GET /repos/django/django/commits
$ curl https://api.github.com/orgs/django/repos
$ curl https://api.github.com/repos/django/django/commits