Encapsulation et appel de l'API Python3

1. Encapsulation d'API

API (Application Programming Interface, interface de programmation d'applications) sont des fonctions prédéfinies, le but est de fournir aux applications et aux développeurs la possibilité d'accéder à un ensemble de routines basées sur un logiciel ou un matériel, sans avoir à accéder au code source, ou comprendre les détails du mécanisme de fonctionnement interne.

L'interface de Python3 est WSGI : Web Server Gateway Interface.

La définition de l'interface WSGI est très simple, elle ne demande qu'aux développeurs web d'implémenter une fonction pour répondre aux requêtes HTTP. Jetons un coup d'œil à la version Web la plus simple Hello, web!:

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, web!</h1>']

La fonction application() ci-dessus est une fonction de traitement HTTP conforme à la norme WSGI, et elle reçoit deux paramètres :

  • environ : un objet dict contenant toutes les informations de requête HTTP ;

  • start_response : une fonction qui envoie une réponse HTTP.

Dans la fonction application(), appelez :

start_response('200 OK', [('Content-Type', 'text/html')])

L'en-tête de la réponse HTTP est envoyé. Notez que l'en-tête ne peut être envoyé qu'une seule fois, c'est-à-dire que start_response()la fonction ne peut être appelée qu'une seule fois. start_response()La fonction reçoit deux paramètres, l'un est le code de réponse HTTP et l'autre est un ensemble d'en-têtes HTTP représentés par une liste, et chaque en-tête est représenté par un tuple contenant deux chaînes.

Normalement, l'en-tête Content-Type doit être envoyé au navigateur. De nombreux autres en-têtes HTTP couramment utilisés doivent également être envoyés.

Ensuite, la valeur de retour de la fonction b'<h1>Hello, web!</h1>'sera envoyée au navigateur en tant que corps de la réponse HTTP.

Avec WSGI, ce qui nous intéresse, c'est comment obtenir les informations de requête HTTP à partir de l'objet environ dict, puis construire du HTML, envoyer l'en-tête via start_response() et enfin renvoyer le corps.

L'ensemble de la fonction application() elle-même n'implique aucune partie de l'analyse HTTP, c'est-à-dire que le code sous-jacent n'a pas besoin d'être écrit par nous-mêmes, nous sommes uniquement responsables de la manière de répondre aux demandes à un niveau supérieur.

Mais attendez, comment cette fonction application() est-elle appelée ? Si nous l'appelons nous-mêmes, nous ne pouvons pas fournir les deux paramètres environ et start_response, et les octets renvoyés ne peuvent pas être envoyés au navigateur.

La fonction application() doit donc être appelée par le serveur WSGI. Il existe de nombreux serveurs conformes à la spécification WSGI, et nous pouvons en choisir un à utiliser. Mais maintenant, nous voulons juste tester dès que possible que la fonction application () que nous avons écrite peut vraiment générer du HTML vers le navigateur, nous devons donc trouver rapidement le serveur WSGI le plus simple et exécuter notre application Web.

Python3 a un serveur WSGI intégré.Ce module est appelé wsgiref, qui est une implémentation de référence d'un serveur WSGI écrit en Python pur. La soi-disant "implémentation de référence" signifie que l'implémentation est entièrement conforme à la norme WSGI, mais ne prend en compte aucune efficacité opérationnelle et n'est utilisée que pour le développement et les tests.

Exécutez le service WSGI

Commençons par écrire hello.py pour implémenter la fonction de traitement WSGI de l'application Web :

# hello.py

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, web!</h1>']

Ensuite, écrivez un server.py responsable du démarrage du serveur WSGI et du chargement de la fonction application() :

# server.py
# 从wsgiref模块导入:
from wsgiref.simple_server import make_server
# 导入我们自己编写的application函数:
from hello import application

# 创建一个服务器,IP地址为空,端口是8080,处理函数是application:
httpd = make_server('', 8080, application)
print('Serving HTTP on port 8080...')
# 开始监听HTTP请求:
httpd.serve_forever()

résultat de l'opération :

  • Démarrer WSGI

    Geek-Mac:Downloads zhangyi$ python3 server.py 
    Serving HTTP on port 8080...
  • accéder à l'API

    Geek-Mac:Downloads zhangyi$ curl "localhost:8080/"
    <h1>Hello, web!</h1>Geek-Mac:Downloads zhangyi$

Il s'agit de l'application WSGI la plus simple, puis écrivez un programme simple pour tester vous-même l'API dans le travail quotidien

exemple

api.py

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import json
# 导入 urllib.parse 模块的 parse_qs 方法
from urllib.parse import parse_qs
from wsgiref.simple_server import make_server


def api(app):

    def application(environ, start_response):

        start_response('200 OK', [('Content-Type', 'text/html')])
        # 获取当前get请求的所有数据,返回是string类型
        parse = parse_qs(environ['QUERY_STRING'])
        data = json.dumps(app(parse))

        # 返回值是 UTF-8
        return [data.encode('utf-8')]

    def run():

        httpd = make_server('', 8080, application)
        print("Serving HTTP on port 8080 ...")
        httpd.serve_forever()

    # 外部模块调用才执行
    if __name__ != "__main__":
        run()

app.py

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

# API 调用实例
# http://127.0.0.1:8080/?name=Geek&user=root

# 导入 api 模块的 api 方法,当然也可以将 api 模块做成一个包,方便调用
from api import api


# 使用装饰器的形式调用函数
@api
def app(parse):

    # 使用 urllib.parse 模块的 parse_qs.get 方法获取 url 中字段的值
    name = parse.get('name', [''])[0]
    user = parse.get('user', [''])[0]

    # 将获取的值写到字典中
    data = {'name': name, 'user': user}

    return data

résultat de l'opération :

  • Démarrer WSGI

    Geek-Mac:API zhangyi$ python3 app.py 
    Serving HTTP on port 8080 ...
  • accéder à l'API

    Geek-Mac:API zhangyi$ curl "http://127.0.0.1:8080/?name=Geek&user=root"
    {"name": "Geek", "user": "root"}Geek-Mac:API zhangyi$

Le plus grand avantage de l'utilisation d'un décorateur est qu'il réduit la complexité du programme. Nous n'avons qu'à nous soucier des fonctions que nous écrivons.  app Enfin, en utiliser un au-dessus de la fonction  @api peut faire exécuter le programme directement, ce qui accélère considérablement l'efficacité du développement.

2. Appel API

L'appel API peut utiliser le module fourni avec Python 3.  urllibVoici un module tiers plus utile  requests.

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

# 安装requests ==> sudo pip3 install requests

import requests


# 调用 API 的 GET 请求
URL = "http://127.0.0.1:8080/?name=Geek&user=root"
data = requests.get(url = URL)

# 获取返回状态
print (data.status_code)
# 获取返回URL
print (data.url)
# 获取返回数据
print (data.text)
# 获取返回 json 解析数据
print (data.json())

résultat de l'opération :

Geek-Mac:Downloads zhangyi$ python3 API.py 
200
http://127.0.0.1:8080/?name=Geek&user=root
{"name": "Geek", "user": "root"}
{'name': 'Geek', 'user': 'root'}

Ceci est juste  requestsl'utilisation GET la plus simple, ainsi que l'utilisation POST, le passage de paramètres de dictionnaire et d'autres utilisations plus détaillées, veuillez visiter le site officiel : http://cn.python-requests.org/zh_CN/latest/

3. Spécification d'écriture d'API REST

Cela peut se résumer en une phrase : REST est le principe directeur de la conception architecturale que toutes les applications Web doivent respecter.

Representational State Transfer, la traduction est "representational state transfer", Wikipedia a une description détaillée : https://zh.wikipedia.org/wiki/Representational State Transfer. 

Orienté ressources est la caractéristique la plus évidente de REST, un ensemble d'opérations différentes pour la même ressource. Une ressource est un concept abstrait qui peut être nommé sur le serveur. Les ressources sont organisées autour de noms, et la première chose sur laquelle se concentrer est les noms. REST nécessite que diverses opérations sur les ressources soient effectuées via une interface unifiée. Seul un ensemble limité d'opérations peut être effectué sur chaque ressource. (7 méthodes HTTP : GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS)

Que sont les API RESTful ?

Une API conforme à la conception de l'architecture REST.

Résumer

Une API conforme à la norme de conception REST, c'est-à-dire une API RESTful. Les normes et directives suivies par la conception de l'architecture REST sont les performances du protocole HTTP, c'est-à-dire que le protocole HTTP est un modèle de conception appartenant à l'architecture REST. Par exemple, sans état, demande-réponse.

4. Directives de conception d'API RESTful

Réimprimé du blog de Ruan Yifeng : http://www.ruanyifeng.com/blog/2014/05/restful_api

L'application Web est divisée en deux parties, le front-end et le back-end. La tendance de développement actuelle est que les terminaux frontaux apparaissent à l'infini (téléphones portables, tablettes, ordinateurs de bureau, autres appareils spécialisés...).

Par conséquent, il doit y avoir un mécanisme unifié pour faciliter la communication entre les différents appareils frontaux et le back-end. Cela a conduit à la popularité de l'architecture API, et même à l'idée de conception de "API First". L'API RESTful est un ensemble relativement mature de théorie de conception d'API pour les applications Internet. J'ai écrit un article "Comprendre l'architecture RESTful" avant d'explorer comment comprendre ce concept.

Aujourd'hui, je vais présenter les détails de conception de l'API RESTful et expliquer comment concevoir une API raisonnable et facile à utiliser.

1. Accord

Le protocole de communication entre l'API et l'utilisateur utilise toujours le protocole HTTPs.

2. Nom de domaine

L'API doit être déployée sous un nom de domaine dédié autant que possible.

https://api.example.com

S'il est déterminé que l'API est très simple et qu'il n'y aura pas d'extension supplémentaire, elle peut être considérée comme placée sous le nom de domaine principal.

https://example.org/api/

3. Gestion des versions

Le numéro de version de l'API doit être inséré dans l'URL.

https://api.example.com/v1/

Une autre façon consiste à mettre le numéro de version dans les informations d'en-tête HTTP, mais ce n'est pas aussi pratique et intuitif que de le mettre dans l'URL. Github adopte cette pratique.

4. Chemin (point final)

Le chemin, également appelé "endpoint", indique l'URL spécifique de l'API.

Dans l'architecture RESTful, chaque URL représente une ressource (ressource), il ne peut donc y avoir aucun verbe dans l'URL, uniquement des noms, et les noms utilisés correspondent souvent aux noms de table de la base de données. D'une manière générale, les tables de la base de données sont des "collections" du même type d'enregistrements, donc les noms dans l'API doivent également utiliser des pluriels.

Par exemple, s'il existe une API qui fournit des informations sur un zoo, y compris des informations sur divers animaux et employés, son chemin doit être conçu comme suit.

https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees

5. Verbes HTTP

Les types d'opérations spécifiques pour les ressources sont représentés par des verbes HTTP.

Les verbes HTTP couramment utilisés sont les suivants (les commandes SQL correspondantes sont entre parenthèses).

GET(SELECT):从服务器取出资源(一项或多项)。
POST(CREATE):在服务器新建一个资源。
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
DELETE(DELETE):从服务器删除资源。

Il existe également deux verbes HTTP qui ne sont pas couramment utilisés.

HEAD:获取资源的元数据。
OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。
下面是一些例子。
GET /zoos:列出所有动物园
POST /zoos:新建一个动物园
GET /zoos/ID:获取某个指定动物园的信息
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
DELETE /zoos/ID:删除某个动物园
GET /zoos/ID/animals:列出某个指定动物园的所有动物
DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物

Six, filtrer les informations (Filtrage)

Si le nombre d'enregistrements est important, il est impossible pour le serveur de tous les renvoyer à l'utilisateur. L'API doit fournir des paramètres et filtrer les résultats renvoyés.

Voici quelques paramètres communs.

?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&per_page=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
?animal_type_id=1:指定筛选条件
参数的设计允许存在冗余,即允许API路径和URL参数偶尔有重复。比如,GET /zoo/ID/animals 与 GET /animals?zoo_id=ID 的含义是相同的。

7. Codes d'état

Les codes d'état communs et les informations d'invite renvoyées par le serveur à l'utilisateur sont les suivants (le verbe HTTP correspondant au code d'état est entre crochets).

200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。

Voir ici pour une liste complète des codes de statut : https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

8. Traitement des erreurs

Si le code d'état est 4xx, un message d'erreur doit être renvoyé à l'utilisateur. En règle générale, error est utilisé comme nom de clé dans les informations renvoyées et le message d'erreur est utilisé comme valeur de clé.

{
    error: "Invalid API key"
}

Neuf, renvoie le résultat

Pour différentes opérations, les résultats renvoyés par le serveur à l'utilisateur doivent répondre aux spécifications suivantes.

GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档

10. API hypermédia

L'API RESTful est préférable pour réaliser Hypermedia, c'est-à-dire pour fournir des liens dans les résultats renvoyés vers d'autres méthodes d'API, afin que les utilisateurs puissent savoir quoi faire ensuite sans consulter la documentation.

Par exemple, lorsqu'un utilisateur fait une requête au répertoire racine de api.example.com, il obtiendra un tel document.

{"link": {
  "rel":   "collection https://www.example.com/zoos",
  "href":  "https://api.example.com/zoos",
  "title": "List of zoos",
  "type":  "application/vnd.yourformat+json"
}}

Le code ci-dessus indique qu'il y a un attribut de lien dans le document, et l'utilisateur saura quelle API appeler ensuite après avoir lu cet attribut. rel indique la relation entre cette API et l'URL actuelle (relation de collection et l'URL de la collection est donnée), href indique le chemin de l'API, title indique le titre de l'API et type indique le type de retour.

La conception de l'API Hypermedia s'appelle HATEOAS. L'API de Github est conçue comme ceci. En visitant api.github.com, vous obtiendrez une liste d'URL pour toutes les API disponibles.

{
  "current_user_url": "https://api.github.com/user",
  "authorizations_url": "https://api.github.com/authorizations",
  // ...
}

Comme on peut le voir ci-dessus, si vous souhaitez obtenir les informations de l'utilisateur actuel, vous devez visiter api.github.com/user, puis vous obtiendrez les résultats suivants.

{
  "message": "Requires authentication",
  "documentation_url": "https://developer.github.com/v3"
}

Le code ci-dessus indique que le serveur donne les informations d'invite et l'URL du document.

11. Autres

(1) L'authentification API doit utiliser le framework OAuth 2.0.

(2) Le format de données renvoyé par le serveur doit essayer d'utiliser JSON au lieu de XML.

Je suppose que tu aimes

Origine blog.csdn.net/onebound_linda/article/details/131914900
conseillé
Classement