Comment utiliser les API Web dans Python 3

introduction

Une API, ou interfaceApplicationProgramI, permet aux développeurs d'intégrer une application à une autre. Ils exposent de manière limitée certaines des tâches internes d’un programme.

Vous pouvez utiliser des API pour obtenir des informations d'autres programmes ou pour automatiser des tâches que vous effectuez normalement dans votre navigateur Web. Parfois, vous pouvez utiliser des API pour faire des choses que vous ne pouvez pas faire autrement. Un nombre surprenant de sites Web proposent des API Web aux côtés d'un site Web ou d'une application mobile plus familiers, notamment Twitter, Facebook, GitHub et DigitalOcean.

Si vous avez parcouru certains tutoriels surhow to code in Python 3 et que vous êtes à l'aise avec la syntaxe, la structure et certainsfunctions intégrés de Python, vous pouvez écrire des programmes Python qui tirent parti de votre favori Apis.

Dans ce guide, vous apprendrez à utiliser Python avec lesDigitalOcean API pour récupérer des informations sur votre compte DigitalOcean. Ensuite, nous verrons comment vous pouvez appliquer ce que vous avez appris àGitHub’s API.

Une fois que vous avez terminé, vous comprendrez les concepts communs aux API Web et vous disposerez d’un processus étape par étape et d’exemples de code de travail que vous pourrez utiliser pour tester les API d’autres services.

Conditions préalables

Avant de commencer ce guide, vous aurez besoin des éléments suivants:

[[step-1 -—- get-familiar-with-an-api]] == Étape 1 - Se familiariser avec une API

La première étape de l’utilisation d’une nouvelle API consiste à trouver la documentation et à vous repérer. La documentation de l'API DigitalOcean commence àhttps://developers.digitalocean.com/. Pour trouver des API pour d'autres services, recherchez le nom du site et «API» - tous les services ne les promeuvent pas sur leurs premières pages.

Certains services ontAPI wrappers. Un wrapper d'API est un code que vous installez sur votre système pour faciliter l'utilisation des API dans le langage de programmation choisi. Ce guide n’utilise pas de wrappers, car ils cachent une grande partie du fonctionnement interne des API et n’exposent souvent pas tout ce que l’API peut faire. Les wrappers peuvent être intéressants lorsque vous souhaitez faire quelque chose rapidement, mais une bonne compréhension de ce que les API peuvent faire vous aidera à déterminer si les wrappers ont un sens pour vos objectifs.

Tout d'abord, regardez l'introduction de l'API DigitalOcean àhttps://developers.digitalocean.com/documentation/v2/ et essayez de comprendre uniquement les bases sur la façon d'envoyer une requête et à quoi s'attendre dans la réponse. À ce stade, vous essayez d’apprendre seulement trois choses:

  1. À quoi ressemble une demande? Sont-ils tous juste des URL? Pour les demandes plus détaillées, comment les données sont-elles formatées? Il s’agit généralement deJSON ou de paramètres de chaîne de requête comme l’utilise un navigateur Web, mais certains utilisent XML ou un format personnalisé.

  2. À quoi ressemble une réponse? Les documents de l'API montreront des exemples de demandes et de réponses. Allez-vous obtenir du JSON, du XML ou un autre type de réponse?

  3. Que contient les en-têtes de requête ou de réponse? Souvent, les en-têtes de demande incluent votre jeton d'authentification et les en-têtes de réponse fournissent des informations actuelles sur votre utilisation du service, telles que votre distance par rapport à une limite de débit.

L'API DigitalOcean utilise HTTPmethods (parfois appeléverbs) pour indiquer si vous essayez de lire des informations existantes, de créer de nouvelles informations ou de supprimer quelque chose. Cette partie de la documentation explique quelles méthodes sont utilisées et à quelles fins. En règle générale, une demande GET est plus simple qu’un POST, mais lorsque vous aurez terminé, vous ne remarquerez plus vraiment de différence.

La section suivante de la documentation de l'API explique comment le serveur répondra à vos demandes. En général, une requête réussit ou échoue. En cas d'échec, la cause est soit un problème avec la demande, soit un problème sur le serveur. Toutes ces informations sont communiquées à l'aide deHTTP status codes, qui sont des nombres à 3 chiffres divisés en catégories.

  • La série200 signifie «succès» - votre demande était valide, et la réponse est ce qui en découle logiquement.

  • La série400 signifie «mauvaise requête» - quelque chose n'allait pas avec la requête, donc le serveur ne l'a pas traitée comme vous le souhaitiez. Les causes courantes des erreurs de niveau HTTP400ont des requêtes mal formatées et des problèmes d'authentification.

  • La série500 signifie «erreur du serveur» - votre demande a peut-être été correcte, mais le serveur n’a pas pu vous donner une bonne réponse pour le moment pour des raisons indépendantes de votre volonté. Celles-ci devraient être rares, mais vous devez être conscient de la possibilité pour pouvoir les gérer dans votre code.

Votre code doit toujours vérifier le code de statut HTTP pour toute réponse avant d'essayer de faire quoi que ce soit avec elle. Si vous ne le faites pas, vous perdrez du temps à résoudre des problèmes avec des informations incomplètes.

Maintenant que vous savez comment envoyer une demande et ce qu’il faut rechercher dans la réponse, il est temps d’envoyer cette première demande.

[[step-2 -—- getting-information-from-the-web-api]] == Étape 2 - Obtenir des informations à partir de l'API Web

Votre compte DigitalOcean contient des informations administratives que vous n'avez peut-être pas vues dans l'interface utilisateur Web. Une API peut vous donner une vue différente d'informations familières. Le simple fait de voir cette vue alternative peut parfois susciter des idées sur ce que vous pourriez faire avec une API ou révéler des services et des options que vous ne connaissiez pas.

Commençons par créer un projet pour nos scripts. Créez un nouveau répertoire pour le projet appeléapis:

mkdir apis

Puis naviguez dans ce nouveau répertoire:

cd apis

Créez une nouvelle virtualenv pour ce projet:

python3 -m venv apis

Activer le virtualenv:

source apis/bin/activate

Ensuite, installez la bibliothèquerequests, que nous utiliserons dans nos scripts pour effectuer des requêtes HTTP dans nos scripts:

pip install requests

Avec l'environnement configuré, créez un nouveau fichier Python appelédo_get_account.py et ouvrez-le dans votre éditeur de texte. Démarrez ce programme parimporting libraries pour travailler avec les requêtes JSON et HTTP.

do_get_account.py

import json
import requests

Ces instructionsimport chargent du code Python qui nous permet de travailler avec le format de données JSON et le protocole HTTP. Nous utilisons ces bibliothèques car nous ne sommes pas intéressés par les détails d’envoi de requêtes HTTP ou d’analyse et de création de fichiers JSON valides; nous voulons simplement les utiliser pour accomplir ces tâches. Tous nos scripts dans ce tutoriel vont commencer comme ceci.

Ensuite, nous voulons configurer certainsvariables pour contenir des informations qui seront les mêmes dans chaque requête. Cela nous évite d'avoir à le taper encore et encore, et nous donne un seul endroit pour faire des mises à jour en cas de changement. Ajoutez ces lignes au fichier, après les instructionsimport.

do_get_account.py

...
api_token = 'your_api_token'
api_url_base = 'https://api.digitalocean.com/v2/'

La variableapi_token est une chaîne qui contient votre jeton API DigitalOcean. Remplacez la valeur dans l'exemple par votre propre jeton. La variableapi_url_base est la chaîne qui commence chaque URL dans l'API DigitalOcean. Nous y ajouterons au besoin plus tard dans le code.

Ensuite, nous devons configurer les en-têtes de requête HTTP de la manière décrite par la documentation de l'API. Ajoutez ces lignes au fichier pour configurer undictionary contenant vos en-têtes de requête:

do_get_account.py

...
headers = {'Content-Type': 'application/json',
           'Authorization': 'Bearer {0}'.format(api_token)}

Cela définit deux en-têtes à la fois. L'en-têteContent-Type indique au serveur d'attendre des données au format JSON dans le corps de la requête. L'en-têteAuthorization doit inclure notre jeton, nous utilisons donc la logique de formatage de chaîne de Python pour insérer notre variableapi_token dans la chaîne lorsque nous créons la chaîne. Nous aurions pu placer le jeton ici sous forme de chaîne littérale, mais sa séparation facilite plusieurs choses plus tard:

  • Si vous devez remplacer le jeton, il est plus facile de savoir où le faire quand il s’agit d’une variable distincte.

  • Si vous souhaitez partager votre code avec quelqu'un, il est plus facile de supprimer votre jeton d'API et de permettre à votre ami de savoir où placer le sien.

  • C'est auto-documenté. Si le jeton de l'API est uniquement utilisé en tant que littéral de chaîne, il est possible que quelqu'un qui lit votre code ne comprenne pas ce qu'il recherche.

Maintenant que ces informations de configuration sont couvertes, il est temps d’envoyer la demande. Vous avez peut-être tendance à simplement commencer à créer et à envoyer les demandes, mais il existe un meilleur moyen. Si vous mettez cette logique dans une fonction qui gère l’envoi de la demande et lit la réponse, vous devrez réfléchir un peu plus clairement à ce que vous faites. Vous obtiendrez également un code qui simplifie les tests et la réutilisation. C’est ce que nous allons faire.

Cette fonction utilisera les variables que vous avez créées pour envoyer la demande et renvoyer les informations de compte dans un dictionnaire Python.

Afin de garder la logique claire à ce stade précoce, nous ne ferons pas encore de traitement d'erreur détaillé, mais nous l'ajouterons assez tôt.

Définissez la fonction qui récupère les informations du compte. C’est toujours une bonne idée de nommer une fonction après ce qu’elle fait: celle-ci obtient les informations du compte, nous l’appellerons doncget_account_info:

do_get_account.py

...
def get_account_info():

    api_url = '{0}account'.format(api_url_base)

    response = requests.get(api_url, headers=headers)

    if response.status_code == 200:
        return json.loads(response.content.decode('utf-8'))
    else:
        return None

Nous construisons la valeur pourapi_url en utilisant la méthode de formatage de chaîne de Python similaire à la façon dont nous l'avons utilisée dans les en-têtes; nous ajoutons l'URL de base de l'API devant la chaîneaccount pour obtenir l'URLhttps://api.digitalocean.com/v2/account, l'URL qui doit renvoyer les informations de compte.

La variableresponse contient un objet créé par le Pythonrequestsmodule. Cette ligne envoie la demande à l'URL créée avec les en-têtes que nous avons définis au début du script et renvoie la réponse de l'API.

Ensuite, examinons le code d’état HTTP de la réponse.

S'il s'agit de200, une réponse réussie, nous utilisons la fonctionloads du modulejson pour charger une chaîne au format JSON. La chaîne que nous chargeons est le contenu de l'objetresponse,response.content. La partie.decode('utf-8') indique à Python que ce contenu est encodé à l'aide du jeu de caractères UTF-8, comme toutes les réponses de l'API DigitalOcean le seront. Le modulejson crée un objet à partir de cela, que nous utilisons comme valeur de retour pour cette fonction.

Si la réponse étaitnot200, alors nous renvoyonsNone, qui est une valeur spéciale en Python que nous pouvons vérifier lorsque nous appelons cette fonction. Vous remarquerez que nous ignorons simplement les erreurs à ce stade. C'est pour garder la logique du «succès» claire. Nous ajouterons bientôt une vérification d'erreur plus complète.

Maintenant, appelez cette fonction, vérifiez qu’elle a reçu une bonne réponse et imprimez les détails renvoyés par l’API:

do_get_account.py

...
account_info = get_account_info()

if account_info is not None:
    print("Here's your info: ")
    for k, v in account_info['account'].items():
        print('{0}:{1}'.format(k, v))

else:
    print('[!] Request Failed')

account_info = get_account_info() définit la variableaccount_info sur tout ce qui est revenu de l'appel àget_account_info(), donc ce sera soit la valeur spécialeNone, soit la collection d'informations sur le Compte.

Si ce n'est pasNone, alors nous imprimons chaque information sur sa propre ligne en utilisant la méthodeitems() que tous les dictionnaires Python ont.

Sinon (c'est-à-dire siaccount_info estNone), nous imprimons un message d'erreur.

Laissons la pause une minute ici. Cette instructionif avec le double négatif peut sembler gênante au début, mais c'est un idiome Python courant. Sa vertu est de garder le code qui s'exécute en cas de succès très proche desconditional plutôt qu'après avoir traité les cas d'erreur.

Si vous préférez, vous pouvez le faire dans l'autre sens, et écrire ce code vous-même peut être un bon exercice. Au lieu deif account_info is not None:, vous pouvez commencer parif account_info is None: et voir comment le reste se met en place.

Enregistrez le script et essayez-le:

python do_get_account.py

La sortie ressemblera à ceci:

OutputHere's your info:
droplet_limit:25
email:[email protected]
status:active
floating_ip_limit:3
email_verified:True
uuid:123e4567e89b12d3a456426655440000
status_message:

Vous savez maintenant comment récupérer les données d'une API. Ensuite, nous allons passer à quelque chose d'un peu plus intéressant: utiliser une API pour modifier les données.

[[step-3 -—- modifying-information-on-the-server]] == Étape 3 - Modification des informations sur le serveur

Après avoir utilisé une requête en lecture seule, il est temps de commencer à apporter des modifications. Explorons cela en utilisant Python et l’API DigitalOcean pour ajouter une clé SSH à votre compte DigitalOcean.

Tout d'abord, jetez un œil à la documentation de l'API pour les clés SSH, disponible surhttps://developers.digitalocean.com/documentation/v2/#ssh-keys.

L'API vous permet de répertorier les clés SSH actuelles de votre compte et d'en ajouter de nouvelles. La demande pour obtenir une liste de clés SSH ressemble beaucoup à celle pour obtenir les informations de compte. La réponse est cependant différente: contrairement à un compte, vous pouvez avoir zéro, une ou plusieurs clés SSH.

Créez un nouveau fichier pour ce script appelédo_ssh_keys.py et démarrez-le exactement comme le dernier. Importez les modulesjson etrequests pour ne pas avoir à vous soucier des détails de JSON ou du protocole HTTP. Ajoutez ensuite votre jeton d'API DigitalOcean en tant que variable et configurez les en-têtes de requête dans un dictionnaire.

do_ssh_keys.py

import json
import requests


api_token = 'your_api_token'
api_url_base = 'https://api.digitalocean.com/v2/'
headers = {'Content-Type': 'application/json',
           'Authorization': 'Bearer {0}'.format(api_token)}

La fonction que nous allons créer pour obtenir les clés SSH est similaire à celle utilisée pour obtenir les informations de compte, mais cette fois, nous allons gérer les erreurs plus directement.

Tout d'abord, nous allons effectuer l'appel API et stocker la réponse dans une variable de réponseresponse. Lesapi_urlne seront cependant pas les mêmes que dans le script précédent; cette fois, il doit pointer vershttps://api.digitalocean.com/v2/account/keys.

Ajoutez ce code au script:

do_ssh_keys.py

...
def get_ssh_keys():

    api_url = '{0}account/keys'.format(api_url_base)

    response = requests.get(api_url, headers=headers)

Ajoutons maintenant un peu de gestion des erreurs en regardant le code d’état HTTP dans la réponse. S'il s'agit de200, nous renverrons le contenu de la réponse sous forme de dictionnaire, comme nous l'avons fait auparavant. S'il s'agit d'autre chose, nous afficherons un message d'erreur utile associé au type de code d'état, puis nous retourneronsNone.

Ajoutez ces lignes à la fonctionget_ssh_keys:

do_ssh_keys.py

...

    if response.status_code >= 500:
        print('[!] [{0}] Server Error'.format(response.status_code))
        return None
    elif response.status_code == 404:
        print('[!] [{0}] URL not found: [{1}]'.format(response.status_code,api_url))
        return None
    elif response.status_code == 401:
        print('[!] [{0}] Authentication Failed'.format(response.status_code))
        return None
    elif response.status_code == 400:
        print('[!] [{0}] Bad Request'.format(response.status_code))
        return None
    elif response.status_code >= 300:
        print('[!] [{0}] Unexpected Redirect'.format(response.status_code))
        return None
    elif response.status_code == 200:
        ssh_keys = json.loads(response.content.decode('utf-8'))
        return ssh_keys
    else:
        print('[?] Unexpected Error: [HTTP {0}]: Content: {1}'.format(response.status_code, response.content))
    return None

Ce code gère six conditions d'erreur différentes en examinant le code d'état HTTP dans la réponse.

  • Un code de500 ou supérieur indique un problème sur le serveur. Celles-ci doivent être rares et ne sont pas causées par des problèmes liés à la demande. Nous n'imprimons donc que le code d'état.

  • Un code de404 signifie «non trouvé», ce qui provient probablement d'une faute de frappe dans l'URL. Pour cette erreur, nous imprimons le code d'état et l'URL qui y ont conduit afin que vous puissiez voir pourquoi cela a échoué.

  • Un code de401 signifie que l'authentification a échoué. La cause la plus probable en est unapi_key incorrect ou manquant.

  • Un code dans la plage300 indique une redirection. L’API DigitalOcean n’utilise pas de redirections, ce qui ne devrait donc jamais se produire. Même si nous gérons les erreurs, la vérification n’est pas compliquée. Un grand nombre de bugs sont causés par des choses que le programmeur pensait ne devraient jamais se produire.

  • Un code de200 signifie que la demande a été traitée avec succès. Pour cela, nous n’imprimons rien. Nous renvoyons simplement les clés ssh sous forme d'objet JSON, en utilisant la même syntaxe que celle utilisée dans le script précédent.

  • Si le code de réponse était autre chose, nous l’imprimons comme une «erreur inattendue».

Cela devrait permettre de gérer toutes les erreurs susceptibles d’entraîner l’appel de l’API. À ce stade, nous avons soit un message d'erreur et l'objetNone, soit nous avons réussi et un objet JSON contenant zéro ou plusieurs clés SSH. Notre prochaine étape consiste à les imprimer:

do_ssh_keys.py

...

ssh_keys = get_ssh_keys()

if ssh_keys is not None:
    print('Here are your keys: ')
    for key, details in enumerate(ssh_keys['ssh_keys']):
        print('Key {}:'.format(key))
        for k, v in details.items():
            print('  {0}:{1}'.format(k, v))
else:
    print('[!] Request Failed')

Comme la réponse contient unlist (ou un tableau) de clés SSH, nous voulons parcourir toute la liste afin de voir toutes les clés. Nous utilisons la méthodeenumerate de Python pour cela. Ceci est similaire à la méthodeitems disponible pour les dictionnaires, mais fonctionne avec des listes à la place.

Nous utilisonsenumerate et pas seulement unfor loop, car nous voulons être en mesure de dire jusqu'où nous sommes dans la liste pour une clé donnée.

Les informations de chaque clé sont renvoyées sous forme de dictionnaire. Nous utilisons donc le même codefor k,v in details.items():que celui utilisé dans le dictionnaire d'informations de compte dans le script précédent.

Exécutez ce script et vous obtiendrez une liste des clés SSH déjà présentes sur votre compte.

python get_ssh_keys.py

La sortie ressemblera à ceci, selon le nombre de clés SSH que vous avez déjà sur votre compte.

OutputHere are your keys:
Kcy 0:
  id:280518
  name:work
  fingerprint:96:f7:fb:9f:60:9c:9b:f9:a9:95:01:5c:5c:2c:d5:a0
  public_key:ssh-rsa AAAAB5NzaC1yc2cAAAADAQABAAABAQCwgr9Fzc/YTD/V2Ka5I52Rx4I+V2Ka5I52Rx4Ir5LKSCqkQ1Cub+... sammy@work
Kcy 1:
  id:290536
  name:home
  fingerprint:90:1c:0b:ac:fa:b0:25:7c:af:ab:c5:94:a5:91:72:54
  public_key:ssh-rsa AAAAB5NzaC1yc2cAAAABJQAAAQcAtTZPZmV96P9ziwyr5LKSCqkQ1CubarKfK5r7iNx0RNnlJcqRUqWqSt... sammy@home

Maintenant que vous pouvez lister les clés SSH sur votre compte, votre dernier script sera celui qui ajoute une nouvelle clé à la liste.

Avant de pouvoir ajouter une nouvelle clé SSH, nous devons en générer une. Pour un traitement plus complet de cette étape, jetez un œil au tutorielHow to Set Up SSH Keys.

Pour nos besoins, cependant, nous avons simplement besoin d’une clé simple. Exécutez cette commande pour en générer une nouvelle sous Linux, BSD ou MacOS. Vous pouvez le faire sur un Droplet existant, si vous le souhaitez.

ssh-keygen -t rsa

Lorsque vous y êtes invité, entrez le fichier pour enregistrer la clé et ne fournissez pas de phrase secrète.

OutputGenerating public/private rsa key pair.
Enter file in which to save the key (/home/sammy/.ssh/id_rsa): /home/sammy/.ssh/sammy
Created directory '/home/sammy/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/sammy/.ssh/sammy.
Your public key has been saved in /home/sammy/.ssh/sammy.pub.
...

Notez l'emplacement où le fichier de clé publique a été enregistré, car vous en aurez besoin pour le script.

Démarrez un nouveau script Python, appelez-leadd_ssh_key.py et démarrez-le comme les autres:

add_ssh_key.py

import json
import requests


api_token = 'your_api_token'
api_url_base = 'https://api.digitalocean.com/v2/'
headers = {'Content-Type': 'application/json',
           'Authorization': 'Bearer {0}'.format(api_token)}

Nous allons utiliser une fonction pour faire notre demande, mais celle-ci sera légèrement différente.

Créez une fonction appeléeadd_ssh_key qui acceptera deux arguments: le nom à utiliser pour la nouvelle clé SSH et le nom de fichier de la clé elle-même sur votre système local. La fonction feraread the file et effectuera une requête HTTPPOST, au lieu d'unGET:

add_ssh_key.py

...

def add_ssh_key(name, filename):

    api_url = '{0}account/keys'.format(api_url_base)

    with open(filename, 'r') as f:
        ssh_key = f.readline()

    ssh_key = {'name': name, 'public_key': ssh_key}

    response = requests.post(api_url, headers=headers, json=ssh_key)

La lignewith open(filename, 'r') as f: ouvre le fichier en mode lecture seule et la ligne qui suit lit la première (et seule) ligne du fichier, en la stockant dans la variablessh_key.

Ensuite, nous créons un dictionnaire Python appeléssh_key avec les noms et les valeurs attendus par l'API.

Lorsque nous envoyons la demande, cependant, il y a un peu plus de nouveautés. C’est unPOST plutôt qu’unGET, et nous devons envoyer lesssh_key dans le corps de la requêtePOST, encodés en JSON. Le modulerequests gérera les détails pour nous; requests.post lui dit d'utiliser la méthodePOST, et y comprisjson=ssh_key lui dit d'envoyer la variablessh_key dans le corps de la requête, codée en JSON.

Selon l'API, la réponse sera HTTP201 en cas de succès, au lieu de200, et le corps de la réponse contiendra les détails de la clé que nous venons d'ajouter.

Ajoutez le code de gestion des erreurs suivant à la fonctionadd_ssh_key. C'est similaire au script précédent, sauf que cette fois, nous devons rechercher le code201 au lieu de200 pour réussir:

add_ssh_key.py

...
    if response.status_code >= 500:
        print('[!] [{0}] Server Error'.format(response.status_code))
        return None
    elif response.status_code == 404:
        print('[!] [{0}] URL not found: [{1}]'.format(response.status_code,api_url))
        return None
    elif response.status_code == 401:
        print('[!] [{0}] Authentication Failed'.format(response.status_code))
        return None
    elif response.status_code >= 400:
        print('[!] [{0}] Bad Request'.format(response.status_code))
        print(ssh_key )
        print(response.content )
        return None
    elif response.status_code >= 300:
        print('[!] [{0}] Unexpected redirect.'.format(response.status_code))
        return None
    elif response.status_code == 201:
        added_key = json.loads(response.content)
        return added_key
    else:
        print('[?] Unexpected Error: [HTTP {0}]: Content: {1}'.format(response.status_code, response.content))
        return None

Cette fonction, comme les précédentes, renvoie soitNone, soit le contenu de la réponse, nous utilisons donc la même approche que précédemment pour vérifier le résultat.

Ensuite, appelez la fonction et traitez le résultat. Transmettez le chemin d'accès à votre clé SSH nouvellement créée en tant que deuxième argument:

add_ssh_key.py

...
add_response = add_ssh_key('tutorial_key', '/home/sammy/.ssh/sammy.pub')

if add_response is not None:
    print('Your key was added: ' )
    for k, v in add_response.items():
        print('  {0}:{1}'.format(k, v))
else:
    print('[!] Request Failed')

Exécutez ce script et vous obtiendrez une réponse vous indiquant que votre nouvelle clé a été ajoutée.

python add_ssh_key.py

La sortie ressemblera à ceci:

OutputYour key was added:
  ssh_key:{'id': 9458326, 'name': 'tutorial_key', 'fingerprint': '64:76:37:77:c8:c7:26:05:f5:7b:6b:e1:bb:d6:80:da', 'public_key': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCUtY9aizEcVJ65/O5CE6tY8Xodrkkdh9BB0GwEUE7eDKtTh4NAxVjXc8XdzCLKtdMwfSg9xwxSi3axsVWYWBUhiws0YRxxMNTHCBDsLFTJgCFC0JCmSLB5ZEnKl+Wijbqnu2r8k2NoXW5GUxNVwhYztXZkkzEMNT78TgWBjPu2Tp1qKREqLuwOsMIKt4bqozL/1tu6oociNMdLOGUqXNrXCsOIvTylt6ROF3a5UnVPXhgz0qGbQrSHvCEfuKGZ1kw8PtWgeIe7VIHbS2zTuSDCmyj1Nw1yOTHSAqZLpm6gnDo0Lo9OEA7BSFr9W/VURmTVsfE1CNGSb6c6SPx0NpoN sammy@tutorial-test'}

Si vous avez oublié de modifier la condition "succès" pour rechercher HTTP201 au lieu de200, vous verrez une erreur signalée, mais la clé aura quand même été ajoutée. Votre gestion des erreurs vous aurait indiqué que le code d'état était201. Vous devez reconnaître cela en tant que membre de la série200, ce qui indique le succès. Ceci est un exemple de la façon dont la gestion des erreurs de base peut simplifier le dépannage.

Une fois que vous avez ajouté la clé avec ce script, relancez-le pour voir ce qui se passe lorsque vous essayez d’ajouter une clé déjà présente.

L'API renverra une réponse HTTP422, que votre script traduira par un message indiquant «La clé SSH est déjà utilisée sur votre compte.»:

Output[!] [422] Bad Request
{'name': 'tutorial_key', 'public_key': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCUtY9aizEcVJ65/O5CE6tY8Xodrkkdh9BB0GwEUE7eDKtTh4NAxVjXc8XdzCLKtdMwfSg9xwxSi3axsVWYWBUhiws0YRxxMNTHCBDsLFTJgCFC0JCmSLB5ZEnKl+Wijbqnu2r8k2NoXW5GUxNVwhYztXZkkzEMNT78TgWBjPu2Tp1qKREqLuwOsMIKt4bqozL/1tu6oociNMdLOGUqXNrXCsOIvTylt6ROF3a5UnVPXhgz0qGbQrSHvCEfuKGZ1kw8PtWgeIe7VIHbS2zTuSDCmyj1Nw1yOTHSAqZLpm6gnDo0Lo9OEA7BSFr9W/VURmTVsfE1CNGSb6c6SPx0NpoN sammy@tutorial-test'}
b'{"id":"unprocessable_entity","message":"SSH Key is already in use on your account"}'
[!] Request Failed

Maintenant, exécutez à nouveau votre scriptget_ssh_keys.py et vous verrez votre clé nouvellement ajoutée dans la liste.

Avec de petites modifications, ces deux scripts pourraient constituer un moyen rapide d’ajouter de nouvelles clés SSH à votre compte DigitalOcean chaque fois que vous en aurez besoin. Les fonctions connexes de cette API vous permettent de renommer ou de supprimer une clé spécifique en utilisant son ID de clé ou son empreinte digitale unique.

Examinons une autre API et voyons comment les compétences que vous venez d’acquérir se traduisent.

[[step-4 -—- working-with-a-different-api]] == Étape 4 - Travailler avec une API différente

GitHub a aussi une API. Tout ce que vous avez appris sur l’utilisation de l’API DigitalOcean s’applique directement à l’utilisation de l’API GitHub.

Familiarisez-vous avec l'API GitHub de la même manière que vous avez utilisé DigitalOcean. Recherchez lesAPI documentation et parcourez la sectionOverview. Vous constaterez tout de suite que les API GitHub et DigitalOcean partagent certaines similitudes.

Tout d'abord, vous remarquerez qu'il existe une racine commune à toutes les URL d'API:https://api.github.com/. Vous savez comment utiliser cela comme une variable dans votre code pour rationaliser et réduire le risque d’erreurs.

L’API de GitHub utilise JSON comme format de requête et de réponse, comme le fait DigitalOcean, pour que vous sachiez comment effectuer ces requêtes et gérer les réponses.

Les réponses incluent des informations sur les limites de débit dans les en-têtes de réponse HTTP, en utilisant presque les mêmes noms et les mêmes valeurs que DigitalOcean.

GitHub utilise OAuth pour l'authentification et vous pouvez envoyer votre jeton dans un en-tête de requête. Les détails de ce jeton sont un peu différents, mais la façon dont il est utilisé est identique à celle utilisée avec l’API de DigitalOcean.

Il y a aussi des différences. GitHub encourage l'utilisation d'un en-tête de requête pour indiquer la version de l'API que vous souhaitez utiliser. Vous savez comment ajouter des en-têtes aux requêtes en Python.

GitHub souhaite également que vous utilisiez une chaîneUser-Agent unique dans les requêtes, afin qu'ils puissent vous trouver plus facilement si votre code pose des problèmes. Vous vous en occuperez aussi avec un en-tête.

L'API GitHub utilise les mêmes méthodes de requête HTTP, mais en utilise également une nouvelle appeléePATCH pour certaines opérations. L'API GitHub utiliseGET pour lire les informations,POST pour ajouter un nouvel élément etPATCH pour modifier un élément existant. Cette requêtePATCHest le genre de chose que vous voudrez rechercher dans la documentation de l'API.

Tous les appels d'API GitHub ne requièrent pas d'authentification. Par exemple, vous pouvez obtenir une liste des référentiels d’un utilisateur sans avoir besoin d’un jeton d’accès. Créons un script pour faire cette demande et afficher les résultats.

Nous allons simplifier la gestion des erreurs dans ce script et utiliser une seule instruction pour gérer toutes les erreurs possibles. Vous n’avez pas toujours besoin de code pour traiter chaque type d’erreur séparément, mais c’est une bonne habitude de faire quelque chose avec des conditions d’erreur, ne serait-ce que pour vous rappeler que les choses ne se passent pas toujours comme vous le souhaiteriez.

Créez un nouveau fichier appelégithub_list_repos.py dans votre éditeur et ajoutez le contenu suivant, qui devrait vous paraître assez familier:

github_list_repos.py

import json
import requests


api_url_base = 'https://api.github.com/'
headers = {'Content-Type': 'application/json',
           'User-Agent': 'Python Student',
           'Accept': 'application/vnd.github.v3+json'}

Les importations sont les mêmes que celles que nous utilisions. Leapi_url_base est l'endroit où toutes les API GitHub commencent.

Les en-têtes incluent deux des options facultatives que GitHub mentionne dans leur aperçu, plus celle qui dit que nous envoyons des données au format JSON dans notre demande.

Même s’il s’agit d’un petit script, nous allons toujours définir une fonction afin de garder notre logique modulaire et encapsuler la logique pour effectuer la demande. Souvent, vos petits scripts vont devenir plus grands, il est donc utile d’être diligent à ce sujet. Ajoutez une fonction appeléeget_repos qui accepte un nom d'utilisateur comme argument:

github_list_repos.py

...
def get_repos(username):

    api_url = '{}orgs/{}/repos'.format(api_url_base, username)

    response = requests.get(api_url, headers=headers)

    if response.status_code == 200:
        return (response.content)
    else:
        print('[!] HTTP {0} calling [{1}]'.format(response.status_code, api_url))
        return None

À l'intérieur de la fonction, nous construisons l'URL à partir desapi_url_base, du nom de l'utilisateur qui nous intéresse et des parties statiques de l'URL qui indiquent à GitHub que nous voulons la liste des dépôts. Ensuite, nous vérifions le code d’état HTTP de la réponse pour nous assurer qu’il s’agissait de200 (succès). Si cela a réussi, nous retournons le contenu de la réponse. Si ce n’était pas le cas, nous imprimons le code de statut et l’URL que nous avons créés afin que nous puissions avoir une idée des erreurs commises.

Maintenant, appelez la fonction et indiquez le nom d'utilisateur GitHub que vous souhaitez utiliser. Nous utiliseronsoctokit pour cet exemple. Puis imprimez les résultats à l'écran:

github_list_repos.py

...
repo_list = get_repos('octokit')

if repo_list is not None:
    print(repo_list)
else:
    print('No Repo List Found')

Enregistrez le fichier et exécutez le script pour afficher les référentiels de l'utilisateur que vous avez spécifié.

python github_list_repos.py

Vous verrez beaucoup de données dans la sortie car nous n’avons pas analysé la réponse au format JSON dans cet exemple, et nous n’avons pas non plus filtré les résultats au moyen de clés spécifiques. Utilisez ce que vous avez appris dans les autres scripts pour le faire. Examinez les résultats que vous obtenez et voyez si vous pouvez imprimer le nom du référentiel.

Un avantage intéressant de ces API GitHub est que vous pouvez accéder aux demandes pour lesquelles vous n’avez pas besoin d’authentification directement dans votre navigateur Web. Cela vous permet de comparer les réponses à ce que vous voyez dans vos scripts. Essayez de visiterhttps://api.github.com/orgs/octokit/repos dans votre navigateur pour voir la réponse.

A présent, vous savez lire la documentation et écrire le code nécessaire pour envoyer des requêtes plus spécifiques afin de prendre en charge vos propres objectifs avec l'API GitHub.

Vous pouvez trouver le code complet de tous les exemples de ce didacticiel dansthis repository on GitHub.

Conclusion

Dans ce didacticiel, vous avez appris à utiliser les API Web pour deux services différents avec des styles légèrement différents. Vous avez compris l'importance d'inclure du code de gestion des erreurs pour faciliter le débogage et rendre les scripts plus robustes. Vous avez utilisé les modules Pythonrequests etjson pour vous isoler des détails de ces technologies et simplement faire votre travail, et vous avez encapsulé le traitement des requêtes et des réponses dans une fonction pour rendre vos scripts plus modulaires.

De plus, vous devez maintenant suivre un processus répétable lorsque vous apprenez une nouvelle API Web:

  1. Recherchez la documentation et lisez l'introduction pour comprendre les principes de base de la manière d'interagir avec l'API.

  2. Procurez-vous un jeton d'authentification, le cas échéant, et écrivez un script modulaire avec gestion des erreurs de base pour envoyer une demande simple, répondre aux erreurs et traiter la réponse.

  3. Créez les demandes qui vous permettront d'obtenir les informations que vous souhaitez du service.

Maintenant, consolidez ces connaissances nouvellement acquises et trouvez une autre API à utiliser, voire une autre fonctionnalité de l’une des API que vous avez utilisées ici. Un projet de votre part aidera à consolider ce que vous avez appris ici.

Related