IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Comprendre la spécification OpenAPI (Swagger) et apprendre à utiliser Swagger Editor
Par Hinault Romaric

Le , par Hinault Romaric

0PARTAGES

Dans mon précédent billet, j’ai présenté comment intégrer le Framework Swagger dans une application ASP.NET Core Web API.



Pour rappel, Swagger offre des outils permettant de générer la documentation pour son API Web. Il offre également une interface permettant d’explorer et tester les différentes méthodes offertes par le service.

Le framework Swagger pour ASP.NET Core (Swashbuckle.AspNetCore) est une implémentation open source qui repose sur la spécification OpenAPI. Le endpoint JSON retourné par Swashbuckle dans une Web API respecte cette spécification.

Origines du projet OpenAPI

L’open source est un moteur de l’innovation qui a changé le destin de nombreux projets, grâce à la contribution d’une communauté importante. Parmi ceux-ci, figure le projet Swagger.

Swagger est un projet open source lancé par une Startup en 2010. L’objectif est de mettre en place un Framework qui va permettre aux développeurs de documenter et de designer des API, tout en maintenant une synchronisation avec le code.

Parallèlement au développement du Framework, une spécification Swagger a été mise en place pour définir le standard à respecter pour designer et documenter son API. Le projet a attiré l’attention de nombreux développeurs, et est devenu la technologie la plus populaire pour designer et décrire les API RESTful.

L’intérêt de l’industrie pour Swagger a poussé des géants de l’IT à se joindre au développement du projet. Google, IBM ou encore Microsoft ont rejoint SmartBear Software, l’entreprise responsable du développement de la spécification Swagger et les outils associés, pour faire évoluer ce dernier.

En janvier 2016 le projet Swagger Specification a été renommé OpenAPI Specification (OAS) et est passé sous la gouvernance de la fondation Linux. L’OPEN API Initiative a été créé par la fondation pour offrir un cadre de travail aux entreprises participantes. Le projet a été également migré vers un nouveau repository sur GitHub. Plusieurs autres géants de l’IT ont rejoint l’initiative, dont Oracle, Adobe, SAP, SalesForce, etc. À ce jour, plus de 30 entreprises participent au développement de la spécification OpenAPI.

Selon le GitHub du projet, la spécification OpenAPI définie un standard, une interface de description de langage de programmation agnostique pour les API REST, qui permet à la fois aux humains et aux machines de découvrir et comprendre les capacités offertes par un service sans avoir besoin d’accéder à son code, consulter une documentation supplémentaire, ou analyser le trafic réseau.

Lorsqu’une API a été correctement définie avec OpenAPI, les développeurs peuvent comprendre et interagir avec le service avec beaucoup moins d’effort d’implémentation.

Description d’un document OpenAPI

Lorsque vous utilisez la spécification OpenAPI pour designer votre API, vous pouvez entre autres : générer une documentation interactive, générer le code de la documentation, client et serveur. Cela est possible à travers de nombreux projets open source développés autour de la spécification OpenAPI.

Les langages supportés pour designer une API sont JSON et YAML. La spécification définit plusieurs étiquettes qui vont permettre entre autres de:


  • définir les informations générales sur vos API : description, termes d’utilisation, licence, contact, etc.;
  • fournir la liste des services qui seront offerts, avec pour chacun, comment les appeler et la structure de la réponse qui est retournée;
  • définir le chemin pour consommer votre API;
  • etc.


334654

NB: vous pouvez consulter le site suivant pour explorer les différentes étiquettes de la spécification OpenAPI:
http://openapi-specification-visual-documentation.apihandyman.io/

Une fois que vous maitrisez le langage JSON ou YAML et que vous comprenez la structure d’un document OpenAPI, avec un simple éditeur de texte, vous êtes en mesure de designer votre API.

Ci-dessous la structure d’un document YAML OpenAPI:

swagger: '2.0'
info:
version: Version de votre API
title: Nom
description: Description de l'API
termsOfService: Termes d'utilisation
contact:
name: Nom personne de contact
url: Site Web
email: Adesse mail
license:
name: Nom de la licence
url: Site Web ou tenir les informations sur la licence
basePath: "/"
paths:
"Chemin de la l'API":
get:
tags:
- Nom du Tag
summary: Resumé de la méthode qui est exposée
description: Description de la méthode exposée
operationId: Nom de la méthode exposée
consumes: []
produces:
- application/json
responses:
'200':
description: Description de la réponse
schema:
"$ref": "#/definitions/ExempleDefinition"
definitions:
ExempleDefinition:
type: sttring


Exemple de document pour une API Customers

Supposons que je souhaite mettre en place une API Customers. Cette API dispose d’une méthode Get permettant de retourner un Customer à partir de son ID. Ci-dessous la définition d’un Customer :

public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EMail { get; set; }
}


Le document OpenAPI pour notre API au format JSON est le suivant

{
"swagger": "2.0",
"info": {
"version": "v2",
"title": "SwaggerDemo API",
"description": "Customers API to demo Swagger",
"termsOfService": "None",
"contact": {
"name": "Hinault Romaric",
"url": "http://rdonfack.developpez.com/",
"email": "hinault@monsite.com"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org"
}
},
"basePath": "/",
"paths": {
"/api/Customers/{id}": {
"get": {
"tags": [
"Customers"
],
"summary": "Retourne un client spécifique à partir de son id",
"description": "Je manque d'imagination",
"operationId": "ApiCustomersByIdGet",
"consumes": [],
"produces": [
"application/json"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "id du client à retourner",
"required": true,
"type": "integer",
"format": "int32"
}
],
"responses": {
"200": {
"description": "client sélectionné",
"schema": {
"$ref": "#/definitions/Customer"
}
}
}
}
}
},
"definitions": {
"Customer": {
"type": "object",
"properties": {
"id": {
"format": "int32",
"type": "integer"
},
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"eMail": {
"type": "string"
}
}
}
}
}


Et le document YAML est le suivant :

swagger: '2.0'
info:
version: v2
title: SwaggerDemo API
description: Customers API to demo Swagger
termsOfService: None
contact:
name: Hinault Romaric
url: http://rdonfack.developpez.com/
email: hinault@monsite.com
license:
name: Apache 2.0
url: http://www.apache.org
basePath: "/"
paths:
"/api/Customers/{id}":
get:
tags:
- Customers
summary: Retourne un client spécifique à partir de son id
description: Je manque d'imagination
operationId: ApiCustomersByIdGet
consumes: []
produces:
- application/json
parameters:
- name: id
in: path
description: id du client à retourner
required: true
type: integer
format: int32
responses:
'200':
description: client sélectionné
schema:
"$ref": "#/definitions/Customer"
definitions:
Customer:
type: object
properties:
id:
format: int32
type: integer
firstName:
type: string
lastName:
type: string
eMail:
type: string


Comme vous pouvez le constater, le format YAML est beaucoup plus facilement éditable pour un humain.

Éditeur

Écrire un document OpenAPI en utilisant un simple éditeur peut être assez fastidieux. Toutefois, il existe un éditeur Swagger en ligne gratuit. Ce dernier offre de nombreuses fonctionnalités intéressantes, dont l’autocompletion.

334639

Swagger Editor dispose d’un éditeur à gauche permettant de designer votre API et d’une fenêtre d’aperçu à droite. Cette fenêtre affiche une documentation interactive sur l’API en cours de conception.

334644

Génération du code de l’API à partir du document OpenAPI

Comme je l’ai souligné plus haut, une fois votre API désignée avec OpenAPI, vous pouvez directement générer la documentation interactive, le code client et serveur. Swagger Editor offre des fonctionnalités de génération du code client et serveur pour un large panel de plateformes et langages de programmation :

334647

En utilisant la fonctionnalité de génération de code serveur pour ASP.NET Core, une application ASP.NET Core Web API est générée avec une solution Visual Studio:

334651

Comme vous pouvez le constater, à partir du document OpenAPI de mon API, le code de l’entité Customer a été automatiquement généré avec les propriétés nécessaires:


public partial class Customer : IEquatable
{

///
/// Initializes a new instance of the class.
///

/// Id.
/// FirstName.
/// LastName.
/// EMail.
public Customer(int? Id = default(int?), string FirstName = default(string), string LastName = default(string), string EMail = default(string))
{
this.Id = Id;
this.FirstName = FirstName;
this.LastName = LastName;
this.EMail = EMail;

}

///
/// Gets or Sets Id
///

[DataMember(Name="id")]
public int? Id { get; set; }
///
/// Gets or Sets FirstName
///

[DataMember(Name="firstName")]
public string FirstName { get; set; }
///
/// Gets or Sets LastName
///

[DataMember(Name="lastName")]
public string LastName { get; set; }
///
/// Gets or Sets EMail
///

[DataMember(Name="eMail")]
public string EMail { get; set; }

///
/// Returns the string presentation of the object
///

/// String presentation of the object
public override string ToString()
{
var sb = new StringBuilder();
sb.Append("class Customer {\n");
sb.Append(" Id: ").Append(Id).Append("\n");
sb.Append(" FirstName: ").Append(FirstName).Append("\n");
sb.Append(" LastName: ").Append(LastName).Append("\n");
sb.Append(" EMail: ").Append(EMail).Append("\n");
sb.Append("}\n");
return sb.ToString();
}

///
/// Returns the JSON string presentation of the object
///

/// JSON string presentation of the object
public string ToJson()
{
return JsonConvert.SerializeObject(this, Formatting.Indented);
}

///
/// Returns true if objects are equal
///

/// Object to be compared
/// Boolean
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((Customer)obj);
}

///
/// Returns true if Customer instances are equal
///

/// Instance of Customer to be compared
/// Boolean
public bool Equals(Customer other)
{

if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;

return
(
this.Id == other.Id ||
this.Id != null &&
this.Id.Equals(other.Id)
) &&
(
this.FirstName == other.FirstName ||
this.FirstName != null &&
this.FirstName.Equals(other.FirstName)
) &&
(
this.LastName == other.LastName ||
this.LastName != null &&
this.LastName.Equals(other.LastName)
) &&
(
this.EMail == other.EMail ||
this.EMail != null &&
this.EMail.Equals(other.EMail)
);
}

///
/// Gets the hash code
///

/// Hash code
public override int GetHashCode()
{
// credit: http://stackoverflow.com/a/263416/677735
unchecked // Overflow is fine, just wrap
{
int hash = 41;
// Suitable nullity checks etc, of course :)
if (this.Id != null)
hash = hash * 59 + this.Id.GetHashCode();
if (this.FirstName != null)
hash = hash * 59 + this.FirstName.GetHashCode();
if (this.LastName != null)
hash = hash * 59 + this.LastName.GetHashCode();
if (this.EMail != null)
hash = hash * 59 + this.EMail.GetHashCode();
return hash;
}
}

#region Operators

public static bool operator ==(Customer left, Customer right)
{
return Equals(left, right);
}

public static bool operator !=(Customer left, Customer right)
{
return !Equals(left, right);
}

#endregion Operators

}

Le code du contrôleur a été généré avec la méthode d’action Get, qui prend en paramètre l’Id. Je n’ai plus qu’à modifier cette méthode d’action pour retourner le client à partir de ma banque de données.

namespace IO.Swagger.Controllers
{
///
///
///

public class CustomersApiController : Controller
{

///
/// Retourne un client specifique à partir de son id
///

/// Je manque d'imagination
/// id du client a retourné
/// client selectionné

[Route("//api/Customers/{id}")]
[SwaggerOperation("ApiCustomersByIdGet")]
[SwaggerResponse(200, type: typeof(Customer))]
public virtual IActionResult ApiCustomersByIdGet(int? id)
{
string exampleJson = null;

var example = exampleJson != null
? JsonConvert.DeserializeObject(exampleJson)
: default(Customer);
return new ObjectResult(example);
}
}
}


Par ailleurs, la classe Startup a été configurée pour utiliser le générateur Swagger et SwaggerUI. Ce qui permet d’offrir un point d’accès à votre documentation à partir de votre application. Et si vous modifiez l’application, le générateur Swagger va générer le document OpenAPI correspondant :

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc()
.AddJsonOptions(
opts => { opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); });

services.AddSwaggerGen();

services.ConfigureSwaggerGen(options =>
{
options.SingleApiVersion(new Info
{
Version = "v1",
Title = "IO.Swagger",
Description = "IO.Swagger (ASP.NET Core 1.0)"
});

options.DescribeAllEnumsAsStrings();

var comments = new XPathDocument($"{AppContext.BaseDirectory}{Path.DirectorySeparatorChar}{_hostingEnv.ApplicationName}.xml");
options.OperationFilter(comments);
options.ModelFilter(comments);
});

}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();

app.UseMvc();

app.UseDefaultFiles();
app.UseStaticFiles();

app.UseSwagger();
app.UseSwaggerUi();
}


Pour l’instant, la génération de code utilise ASP.NET Core 1.0.x.

Lorsque vous voulez créer des API REST, il est assez simple d’utiliser OpenAPI pour designer votre API, ensuite générer le code correspondant. Ce qui offrira un canevas aux développeurs pour les différents services qui seront offerts par l’API. Ces derniers n’auront plus qu’à implémenter la logique métier des services.

Si vous avez déjà créé votre Web API, comme je l’ai présenté dans le tutoriel précédent, vous pouvez simplement configurer le framework Swagger pour générer la documentation à partir du code.

Vous avez lu gratuitement 864 articles depuis plus d'un an.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.

Une erreur dans cette actualité ? Signalez-nous-la !