Cómo utilizar requests de Python con una API Rest
👋 ¡Hola! En el tutorial de esta semana, te voy a explicar como utilizar la librería requests de Python la cual nos permitirá realizar peticiones HTTP extremadamente fáciles.
Qué necesito saber antes de empezar 🤔
Para entender bien este tutorial, necesitarás tener conocimientos de HTTP y API Rest, si no es así, te dejo mi guía 100% gratuita en el que explico el funcionamiento de una API y cómo construirla 👇
Guía para aprender a trabajar con APIs
Ejemplo con el que vamos a trabajar
Para este tutorial vamos a usar una API que he creado para mi guía, la cual te he mencionado anteriormente. En esta API podremos registrarnos y nos permitirá administrar un sistema de tareas. Los datos que emplea esta API estarán "mockeados", eso quiere decir que no persistirán, pero podrás ver su funcionamiento sin problemas.
Librería Requests 📖
Como he comentado antes, la librería requests nos permite hacer peticiones HTTP fácilmente. En su propia documentación indica que está construida para que sea entendida claramente como vais a ver a continuación.
Creación del proyecto
Para este tutorial voy a crear un proyecto que tendrá un entorno virtual y en él, instalaré requests.
python -m venv env
# Windows
.\env\Scripts\activate
# Mac/linux
source env/bin/activate
Instalación de la librería requests
pip install requests
Una vez hecho esto, me he creado un archivo llamado main.py con el siguiente contenido:
import requests
import json
base_url = "https://api-tasks.cosasdedevs.com/v1/"
if __name__ == '__main__':
pass
Como puedes ver, importo las librerías requests y json que la necesitaremos más adelante para codificar unos datos. También he creado una variable con la URL base de la API. Por último, añado el punto de entrada del proyecto. Ahí será donde llamaremos a las funciones que generemos más adelante.
Lo primero que vamos a ver es como realizar una petición con requests para crear un usuario en nuestra API. Si vas a mi guía y buscas como generar un usuario, tenemos la petición en formato CURL así que vamos a traducirla a requests. No os preocupéis si no conocéis CURL, ya que el comando es muy fácil de leer.
Petición en formato CURL:
curl -X POST 'https://api-tasks.cosasdedevs.com/v1/users' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'username=user4&email=user4@cosasdedevs.com&password=admin123'
Si os fijáis, el método a utilizar será de tipo POST, la cabecera nos indica que la información a enviar debe ir en formato de formulario y por último tenemos los parámetros a enviar en formato de query.
Pues bien, la conversión a requests sería así:
def create_user():
url = base_url + "users"
user = {
'username': 'test',
'email': 'test@cosasdedevs.com',
'password': 'admin123',
}
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.request("POST", url, headers=headers, data=user)
print_response(response)
def print_response(response):
print(response.text)
print(response.json())
print(response.status_code)
print(response.headers)
if __name__ == '__main__':
create_user()
Como puedes observar, concateno a la url base la URI para crear un usuario. Después he generado un diccionario con los parámetros para la creación de un usuario que en este caso son username, email y password.
El siguiente paso es crear otro diccionario con las cabeceras que necesitaremos, en este caso la cabecera "Content-type" con valor "application/x-www-form-urlencoded" para indicar que estamos enviando un formulario.
Por último realizamos la petición con requests, el cual recibe como primer parámetro el método que en este caso es POST, como segundo parámetro la URL, en el tercero enviamos las cabeceras y al final los datos del usuario.
También me he creado una función adicional que recibirá la respuesta de requests e imprimiremos los datos más relevantes que son:
"text": Retorna la respuesta del servidor en formato de texto:
{"status":"success","data":{"id":4,"username":"test","email":"test@cosasdedevs.com"}}
"json()": Si la respuesta es un JSON, la convierte a diccionario.
"status_code": El código de estado HTTP en formato numérico. En este caso, al ser una creación, el código que devuelve es el 201.
"headers": Las cabeceras de respuesta de la API.
Si quieres ver un error, podéis forzarlo intentando registrar un usuario que ya exista, por ejemplo utilizando el email "admin@cosasdedevs.com" al intentar registrarte. Si lo haces, verás una respuesta así:
{"status":"error","error":"Email already exists"}
El código de estado HTTP que retornará será 422.
El siguiente caso que vamos a ver es el de como realizar el login. Al igual que en el caso anterior, os dejo el comando CURL y ahora lo traducimos:
curl -X POST 'https://api-tasks.cosasdedevs.com/v1/login' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'email=admin@cosasdedevs.com&password=admin123'
Como puedes observar, también es de tipo POST, la URI es /login, empleamos la misma cabecera de antes y como parámetros enviamos el email y password. Recodad que los usuarios que creéis no existen, así que solo podremos autenticarnos con este email y contraseña.
La conversión a requests quedaría así:
def login():
url = base_url + "login"
auth = {
'email': 'admin@cosasdedevs.com',
'password': 'admin123'
}
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.request("POST", url, headers=headers, data=auth)
print_response(response)
if __name__ == '__main__':
login()
Como ves, es muy similar al caso anterior, así que no me voy a explayar con este caso. Únicamente quiero que te fijes en la respuesta para que veas que todo ha ido bien y que recibimos el token de autenticación que necesitaremos más adelante.
{"status":"success","data":{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7ImlkIjoxfSwiaWF0IjoxNjUzMjE1OTA0LCJleHAiOjE2NTMyMTY4MDR9.ouzH9FdsYLVaLMLW4myrGI9y4zf33Z2T5ceumDueuOI"}}
El siguiente caso que vamos a ver va a ser el de obtener una tarea, así que te dejo el comando CURL y ahora lo convertimos.
curl -X GET 'https://api-tasks.cosasdedevs.com/v1/tasks/30' \
-H 'Authorization: xxxxx'
Como ves, aquí necesitamos el token de autenticación, así que además de crear la función para obtener una tarea, vamos a realizar unas modificaciones en la función login() para que nos retorne el token de autenticación:
def login():
url = base_url + "login"
auth = {
'email': 'admin@cosasdedevs.com',
'password': 'admin123'
}
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.request("POST", url, headers=headers, data=auth)
if(response.status_code == 200):
return response.json()['data']['token']
raise Exception(response.json()['error'])
def get_task_by_id(id):
url = base_url + f"tasks/{id}"
headers = {
'Authorization': login()
}
response = requests.request("GET", url, headers=headers)
print_response(response)
if __name__ == '__main__':
get_task_by_id(30)
Como puedes ver, en la función login(), si recibimos el código de estado esperado, convertimos la respuesta a diccionario y ahí accedemos a la clave donde se almacena el token para retornarlo.
Después tenemos la función get_task_by_id() que recibirá un identificador por parámetro. El siguiente paso es generar el endpoint al que queremos atacar y crear las cabeceras que en este caso solo necesitaremos el token de autenticación. Como puedes ver, genero la clave "Authorization" en la que su valor será la respuesta de la función login().
Por último, vamos a realizar la petición con requests. Fíjate que en este caso el método a utilizar es GET y no necesitamos enviar ningún dato, por lo que obviamos el parámetro "data".
Por último, vamos a ver la acción de producir una tarea, ya que aquí vamos a ver un formato nuevo a la hora de enviar los datos. Dejo aquí la petición CURL para que la tengamos de base.
curl -X POST 'https://api-tasks.cosasdedevs.com/v1/tasks' \
-H 'Authorization: xxxxx' \
-H 'Content-Type: application/json' \
-d '{
"title": "Mi primera tarea"
}'
Si te fijas en las cabeceras, aquí cambia el formato en el que vamos a enviar los datos, ahora, la API los recibirá en formato JSON. En la siguiente línea ya puedes ver que para crear una tarea solo necesitamos enviar un título y como acabo de comentar lo enviamos en formato JSON.
Para traducirlo a requests vamos a crear una función llamada create_task() con el siguiente contenido:
def create_task():
url = base_url + "tasks"
data = {
"title": "New tasks"
}
payload = json.dumps(data)
headers = {
'Authorization': login(),
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print_response(response)
if __name__ == '__main__':
create_task()
Como ves, primero generamos el endpoint, después un diccionario con la información a enviar que posteriormente convertimos a JSON con la función dumps de la librería JSON, la cual importamos al principio del tutorial.
En las cabeceras enviamos nuestro token de autenticación y el "content-type" para indicar en que formato enviamos los datos y por último utilizamos la librería requests para hacer la petición.
Si todo ha ido bien, recibiremos el código de estado 201 y una respuesta similar a esta:
{"status":"success","data":{"task":{"id":151,"user_id":1,"title":"New tasks","created_at":"2022-05-22 12:51:51","updated_at":null,"is_done":false},"msg":"Task has been created successfully"}}
Y listo, con estos casos creo que ya podrás tener una buena base para trabajar con APIs y la librería requests. Si quieres seguir practicando, te recomiendo que realices todos los casos disponibles en mi guía y si tienes alguna duda puedes dejarla en la caja de comentarios 😉.
Espero que este post te ayude y como siempre, te recomiendo seguirme en Twitter para estar al tanto de los nuevo contenido. Ahora también puedes seguirme en Instagram donde estoy subiendo tips, tutoriales en vídeo e información sobre herramientas para developers.
Por último os dejo mi guía para aprender a trabajar con APIs donde explico todo el funcionamiento de una API, el protocolo HTTP y veremos como construir una API con arquitectura REST.
Nos leemos 👋.