Une adresse web qui lance une fonction
Une boutique veut une adresse web, /commandes/ana, qui répond avec les commandes d’Ana. Personne n’a envie de faire tourner un serveur rien que pour cela.
Une API Gateway peut prendre la requête web et la confier à une fonction Lambda. La fonction doit répondre exactement dans la forme que la passerelle attend, même quand la requête est fausse.
À la fin de cette leçon
Remarque
Je peux écrire la réponse qu’une passerelle API attend d’une fonction.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Requête | ce qu’un appelant envoie à une adresse web | |
| Réponse | ce que la fonction renvoie | |
| Code de statut | un nombre qui dit comment la requête s’est passée | 404 |
| En-tête | un détail nommé, envoyé à côté du corps | content-type |
| Corps | le texte principal d’une requête ou d’une réponse |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une requête entre, une réponse sort
La passerelle transforme la requête web en événement. La méthode, comme GET, est dans requestContext.http.method. Le chemin est rawPath.
La fonction renvoie un dictionnaire à trois parties : statusCode, headers et body. Le corps doit être une chaîne, donc on utilise json.dumps. Ce sont les formes documentées, pas la sortie d’une pile que vous auriez déployée vous-même.
Exécutez : la plus petite porte d’entrée
import json
# La forme documentée d’une requête d’API HTTP, réduite.
evenement = {
"requestContext": {"http": {"method": "GET"}},
"rawPath": "/commandes/ana",
"headers": {"accept": "application/json"},
}
def gestionnaire(event, context):
methode = event["requestContext"]["http"]["method"]
chemin = event["rawPath"]
donnees = {"vous_avez_demande": methode + " " + chemin}
return {"statusCode": 200,
"headers": {"content-type": "application/json"},
"body": json.dumps(donnees)}
reponse = gestionnaire(evenement, None)
print(reponse["statusCode"])
print(reponse["body"])
print(type(reponse["body"]).__name__)
# Remplacez "GET" par "POST" dans l’événement et exécutez de nouveau.
Un code de statut dit qui s’est trompé
Un 2 au début, comme 200 ou 201, veut dire que tout va bien. Un 4, comme 400 ou 404, veut dire que l’appelant a demandé quelque chose de faux. Un 5 veut dire que la fonction elle-même a échoué.
Une requête fausse n’est pas une panne. Renvoyez un 4 avec une courte erreur dans le corps. Une fonction qui lève une erreur donne à l’appelant une vague erreur 5xx, et ne lui apprend rien qu’il puisse corriger.
Exemple travaillé : les codes de cette leçon
| Code | Sens | À utiliser quand |
|---|---|---|
| 200 | OK | Vous avez trouvé et renvoyé les données |
| 201 | Créé | Une nouvelle commande a été rangée |
| 400 | Mauvaise requête | Un champ manque ou est faux, ou le corps n’est pas du JSON valide |
| 404 | Introuvable | Aucun tel chemin ou aucune telle commande |
| 405 | Méthode non autorisée | Le chemin existe, la méthode non |
| 415 | Type de contenu non pris en charge | L’en-tête content-type n’est pas application/json |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Erreur fréquente
Attention
Beaucoup laissent la fonction tomber en panne sur une entrée fausse. L’appelant reçoit alors une vague erreur de serveur. Vérifiez d’abord l’entrée. Quand l’appelant est en faute, renvoyez un 4 et dites quoi corriger. Gardez le 5 pour vos propres fautes.
Exécutez : une erreur sous forme de réponse
import json
def repondre(statut, donnees):
return {"statusCode": statut,
"headers": {"content-type": "application/json"},
"body": json.dumps(donnees)}
def gestionnaire(event, context):
# Une clé absente est la faute de l’appelant : répondez 400, ne tombez pas en panne.
if "queryStringParameters" not in event:
return repondre(400, {"erreur": "ajoutez ?client=nom"})
nom = event["queryStringParameters"]["client"]
return repondre(200, {"bonjour": nom})
print(gestionnaire({"queryStringParameters": {"client": "ana"}}, None)["statusCode"])
print(gestionnaire({}, None)["statusCode"])
print(gestionnaire({}, None)["body"])
# Ajoutez une troisième ligne qui appelle gestionnaire avec {"queryStringParameters": {}}. Que se passe-t-il ?
Lisez la requête avec soin
Toutes les clés ne sont pas toujours là. Sans chaîne de requête, queryStringParameters est absente de l’événement. Testez avec in avant de la lire.
Le corps arrive en texte. Si isBase64Encoded est vrai, le texte est encodé : décodez-le d’abord. Les noms d’en-têtes arrivent en minuscules, donc cherchez content-type.
Exécutez : lire un corps en base64
import json
import base64
evenement = {
"body": base64.b64encode(b'{"article": "the"}').decode("utf-8"),
"isBase64Encoded": True,
}
texte = evenement["body"]
print(texte)
if evenement["isBase64Encoded"] is True:
texte = base64.b64decode(texte).decode("utf-8")
print(texte)
print(json.loads(texte)["article"])
# Mettez isBase64Encoded à False et exécutez de nouveau. Qu’est-ce qui ne va plus ?
Ce que ce module n’a pas enseigné
Remarque
Tout s’est passé hors ligne, en Python, sur des réponses de même forme que les vraies. Vous n’avez rien déployé, ouvert aucun vrai compte et vu aucune facture. Vous n’avez pas rencontré le coût d’un service qui reste allumé. Ce sont les étapes suivantes, qui s’apprennent mieux avec quelqu’un qui peut vérifier les réglages de votre compte.