Non classé

Serveurs REST dans Go: Partie 4 – Utilisation d'OpenAPI et de Swagger – Un serveur de qualité

Le 6 février 2021 - 13 minutes de lecture


Ceci est le quatrième article d'une série sur l'écriture de serveurs REST dans Go. En voici un
liste des articles de la série:

Dans cette section, je discuterai de la façon dont OpenAPI et Swagger peuvent être utilisés pour définir REST
API de manière standardisée et comment générer du code Go à partir d'un OpenAPI
spécification.

Problème motivant

Dans la partie 1 de cette série – lorsque nous avons défini l'API REST pour la nôtre
application – j'ai remarqué que la définition de l'API est quelque peu ad hoc, juste une liste de
méthode / types avec quelques commentaires:

POST / task /: crée une tâche, renvoie l'ID
GET / affectation /      : renvoie une seule tâche par ID
GET / task /: renvoie toutes les tâches
SUPPRIMER / tâche /      : supprimer une tâche par ID
GET / tag /      : renvoie la liste des tâches avec cette balise
GET / maturité ///
: renvoie la liste des tâches à payer à cette date

Ne serait-ce pas bien, c'était une manière standard de décrire l'API? UN
standard signifie que la description peut servir de contrat entre les serveurs et
clients. De plus, une description standard sera immédiatement connue des gens
pas étroitement impliqué dans le projet. Il peut également être lisible par machine,
conduit à toutes sortes d'avantages d'automatisation.

Swagger et OpenAPI

Swagger était fondamentalement
publié en 2011 comme IDL pour décrire
API REST.

Logo Swagger

La motivation originale de Swagger était la génération automatique de documentation pour REST
API, ainsi que des exemples d'interactions API

L'année 2014 a été la sortie de la version 2.0, et en 2016, un tas de
les grandes entreprises du secteur ont uni leurs forces pour créer OpenAPI – un de plus
version standardisée de Swagger, avec la version 3.0.

Le site officiel pour tout ce qui concerne Swagger et OpenAPI est https://swagger.io,
pris en charge par Smart Bear Software.

La nomenclature autour de ceci est un peu déroutante, mais le moyen le plus simple de
N'oubliez pas qu'OpenAPI est le nom actuel de la spécification, tandis que Swagger
fait généralement référence à l'outil qui l'entoure (bien que vous puissiez également entendre "Swagger"
spécification ", en particulier lorsqu'il s'agit de versions antérieures à 3.0).

Notre service de tâches avec une définition OpenAPI

Commençons par répéter notre exercice préféré d'écriture sur le service d'affectation,
cette fois en utilisant OpenAPI et Swagger.

Pour ce faire, j'ai passé du temps à lire la documentation d'OpenAPI 3.0 et j'ai lancé
Swagger Editor pour entrer la spécification comme
un fichier YAML. Cela a pris un certain temps et le résultat final est ce fichier.

L'extrait de code suivant est, par exemple, la description de GET / affectation /
request, qui doit renvoyer toutes les tâches. Dans une spécification OpenAPI, nous pouvons
entrez n'importe quel nombre taureau, chacun avec ses différents méthodes (PEU,
POST etc.) Et une description des paramètres et des réponses, ainsi que JSON
formes.

/tâche:
  peu:
    résumé: renvoie une liste de toutes les tâches
    réponses:
      & # 39; 200 & # 39;:
        Description: une plage JSON d'ID de tâche
        Contenu:
          application / json:
            forme:
              type: matrice
              objets:
                $ ref: & # 39; # / composants / formulaires / Tâche & # 39;

composants / formulaires / tâche fait référence à cette définition qui est la nôtre
Tâche modèle:

Composants:
  formes:
    Tâche:
      type: objet
      caractéristiques:
        identifiant:
          type: entier
        texte:
          type: chaîne
        Mots clés:
          type: matrice
          objets:
            type: chaîne
        pourriture:
          type: chaîne
          format: date-heure

Ceci est une description des données forme; notez que nous pouvons spécifier des types pour
champs de données, qui (du moins en théorie) peuvent être utiles pour la génération automatique
validateurs de ces données.

Cet effort a déjà fourni un avantage – une belle documentation colorée pour
Notre API:

Image de documentation générée par Swagger pour l'API REST

Ceci est juste une capture d'écran; la documentation elle-même est cliquable et extensible,
fournit une description claire des paramètres de requête, des réponses et de leur JSON
formulaires, etc.

Cependant, il y a plus. À condition que cette API soit hébergée dans un environnement accessible au public
serveur, nous pouvons interagir avec lui directement à partir de Swagger Editor – tout comme
Fait main boucle commandes, mais d'une manière consciente de la forme générée automatiquement.

Imaginez que vous avez développé l'API de cette tâche et que vous souhaitez maintenant la publier pour l'utiliser dans
une variété de clients (réseau, mobile, etc.); si l'API est spécifiée avec
OpenAPI / Swagger, vous obtenez une documentation automatique et une interface pour les clients
expérimentez avec l'API. Ceci est deux fois plus important lorsque vous avez des consommateurs d'API
qui ne sont pas des ingénieurs SW – par exemple, cela pourrait être des concepteurs UX, des
Rédacteurs de documentation et chefs de produit qui ont besoin de comprendre une API, mais qui peuvent
être moins à l'aise pour lancer des scripts ensemble.

De plus, OpenAPI normalise des choses comme l'autorisation, qui peut également être
très utile par rapport à une description ad hoc.

Il existe plusieurs outils disponibles lorsque vous avez une spécification – par ex. Swagger UI et Swagger Inspector. Vous pouvez même utiliser la spécification pour
aider à intégrer votre serveur REST dans l'infrastructure du fournisseur de cloud; à
GCP a, par exemple, Cloud Endpoints pour OpenAPI pour configurer la surveillance,
analyse et autres fonctions pour les API publiées; L'API est décrite pour l'outil
en utilisant OpenAPI.

Génération automatique d'un échafaudage de serveur Go

La promesse d'OpenAPI / Swagger va au-delà de la documentation; nous pouvons aussi générer
code serveur et client de celui-ci.

J'ai suivi les instructions officielles du projet Swagger codegen pour générer le squelette
un serveur Go. Ensuite, j'ai rempli les gestionnaires pour implémenter notre serveur de tâches. Il est
disponible ici,
avec les étapes que j'ai utilisées écrites dans le fichier README dans ce répertoire. Cette
le serveur passe maintenant tous nos tests automatisés.

Le code généré utilise gorille / mux pour le routage (au même titre que notre approche
et partie 2)
et crée des gestionnaires d'espace réservé dans un fichier nommé api_default.go. J'ai placé
la logique de tâche maintenant connue de ces gestionnaires; par exemple:

func TaskIdDelete(w http.ResponseWriter, r *http.Demande) 
  id, Erreur : = strconv.Atoi(mux.Vars(r)[[[["id"])
  si Erreur ! = zéro 
    http.Erreur(w, Erreur.Erreur(), http.StatusBadRequest)
    revenir
  
  Erreur = boutique.SupprimerTâche(id)
  si Erreur ! = zéro 
    http.Erreur(w, Erreur.Erreur(), http.StatusNotFound)
  

En travaillant là-dessus, j'ai rassemblé quelques notes sur les limites de ce
approche:

  • Le nom de code / package d'importation généré ne fonctionnait pas correctement
    box, du moins pas avec les modules Go. J'ai dû le restructurer un peu.
  • Certains des fichiers générés n'étaient pas conformes gofmt mise en forme pour quelqu'un
    raison.
  • Le code force les globaux sur le serveur; alors que dans les sections précédentes nous l'avons fait
    avait toujours une structure de serveur dont les méthodes étaient enregistrées en tant que gestionnaires (et
    par conséquent, la structure de la structure fonctionnait comme des données partagées), i
    serveur généré par Swagger, les gestionnaires sont des fonctionnalités de premier niveau.
  • Bien que ma définition OpenAPI ait une forme qui force les valeurs entières
    paramètres de chemin spécifiques (par exemple, jour, mois, année pourriture / chemin),
    le serveur généré n'avait aucune validation pour cela. En plus, cependant
    gorille / mux prend en charge les expressions régulières dans les paramètres de chemin, le code généré n'a pas
    même l'utiliser. Le résultat: j'ai dû réécrire manuellement la validation des paramètres.

Dans l'ensemble, les avantages de la génération automatique de code serveur me semblent discutables.
Le temps qu'il gagne est assez petit, étant donné que je devais en écrire un
tas de code de toute façon. De plus, puisque je n'utilise pas l'échafaudage généré
tel quel, s'applique uniquement à tout le temps gagné la première fois. Si je change maintenant
Définition OpenAPI, je ne peux pas simplement demander au générateur de code de mettre à jour mon serveur –
ils se sont déjà séparés.

La swagger codegen l'outil peut également générer clients, inclus pour Go. Cette
peut être utile dans certains cas, même si j'ai trouvé le code client généré par celui-ci
un peu compliqué. Comme auparavant, cela peut probablement servir de bon point de départ
pour écrire votre propre client, mais ne fera probablement pas partie d'un flux de travail continu.

Essais avec des générateurs de code alternatifs

Les spécifications OpenAPI sont écrites en YAML (ou YAML) et ont un format bien documenté.
Par conséquent, il n'est pas surprenant qu'il y ait plus d'un outil simple disponible
pour générer du code serveur à partir d'une spécification. Dans la partie précédente, j'ai couvert l'utilisation
le générateur de code Swagger "officiel", mais il y en a beaucoup plus!

Pour Go, un générateur populaire est un jeu d'enfant. README a cette section:

En quoi est-ce différent du générateur go dans le codegen swagger?

tl; dr La principale différence pour le moment est que cela fonctionne réellement …

Le projet Swagger codegen ne génère qu'un seul client go utilisable et même
là, il ne supportera que les modèles plats. De plus, le serveur go est généré par
le codegen swagger est principalement une souche.

J'essayais de générer un serveur avec go-swagger. Puisque le code qu'il génère est
assez grand, je ne veux pas me connecter; mais je veux partager mes impressions.

Tout d'abord, go-swagger prend uniquement en charge la spécification Swagger 2.0, pas la dernière
version 3.0 d'OpenAPI. C'est assez malheureux, mais j'en ai trouvé un
outils en ligne
qui se convertit de l'un à l'autre, et une version 2.0 de la spécification peut également être
trouvé dans le dépôt.

Le serveur généré par go-swagger est certainement plus fonctionnel que
celui généré par swagger codegen, mais cela coûte quelque chose. Ceci en essence
vous connecte au framework spécifique conçu par go-swagger mainteneurs.
Le code généré a de nombreuses dépendances sur les paquets dans
https://github.com/go-openapi/ organisation, et utilise le code de ces packages
complet pour configurer et exécuter le serveur. Vous obtenez même une analyse personnalisée des indicateurs
paquets – parce que … pourquoi pas?

Si vous aimez le cadre utilisé là-bas, cela pourrait être bon. Mais si tu
Gardez vos propres idées à l'esprit – comme utiliser Gin ou un routeur personnalisé, ce n'est pas
très utile que le code généré soit si significatif.

go-swagger peut également générer un client pour vous, qui est également complet
discuté et significatif. Cela peut être un problème mineur si vous en avez besoin rapidement
générer des codes client pour les tests, cependant.

Génère des spécifications à partir du code

Et si vous avez déjà implémenté votre serveur REST mais que vous aimez vraiment l'idée
d'une spécification OpenAPI pour cela; dans ce cas, il est possible de générer une spécification à partir de
votre code serveur?

Oui! En utilisant des commentaires spéciaux et des outils comme swaggo / swag, la spécification (malheureusement seulement la version 2.0,
à nouveau) sera généré pour vous. Vous pouvez ensuite transmettre cette spécification à d'autres Swagger
des outils pour tous vos besoins en documentation.

En fait, cela semble être une option particulièrement intéressante si vous avez le vôtre
façon d'écrire des serveurs REST et ne veulent pas s'engager uniquement dans un nouveau framework
dans le but d'utiliser Swagger.

Conclusion?

Imaginez que vous avez un programme qui a besoin d'utiliser une API REST, et là
sont deux services qui se disputent votre attention:

  • Le service 1 a une description ad hoc de l'API dans un fichier texte, avec quelques
    essayer boucle commandes pour interagir avec lui.
  • Service 2 a une spécification OpenAPI, avec une documentation agréable et standard
    et des outils pour l'essayer en ligne sans avoir à ouvrir le terminal.

En supposant que tous les autres paramètres sont identiques, quelle API choisirez-vous d'essayer
premier? IMHO les avantages d'OpenAPI pour la documentation et en tant que standard
les contrats entre les serveurs REST et les clients sont évidents. Ce qui est moins évident, c'est
dans quelle mesure nous devrions utiliser notre utilisation des outils Swagger.

J'aimerais décrire mon API avec OpenAPI et utiliser l'outil de documentation, mais
Je veux également être plus prudent lorsqu'il s'agit de générer du code. Personnellement, je voudrais
préfère plus de contrôle sur mon code serveur – quelles dépendances il a et comment il est
structuré. Bien que je vois la valeur de la génération de code serveur pour un prototypage rapide
et l'expérimentation, je n'utiliserais pas un serveur généré automatiquement comme base pour
ma mise en œuvre réelle.

En fait, des outils comme swaggo / swag peut offrir l'équilibre parfait ici. Tu
écrivez votre code serveur en utilisant n'importe quel framework / technique que vous voulez et ajoutez
commentaires magiques pour décrire l'API REST. L'outil génère ensuite OpenAPI
spécification à partir de ces commentaires, et vous pouvez générer de la documentation ou autre chose
de cette spécification. Il y a l'avantage supplémentaire de conserver la source spécifique de vérité
(les commentaires magiques) au plus près du code source qui l'implémente –
toujours une bonne pratique en ingénierie SW.


Commentaires

Laisser un commentaire

Votre commentaire sera révisé par les administrateurs si besoin.