Changes to OpenAPI interpretation in Azure API Management
Providing clean and well-documented APIs is a must and allows your consumers to know what you provide, what they are for and what to expect. Azure API Management released a new version that changes the OpenAPI interpretation. This article dives into the potential impact on your consumer experience
TL;DR - Azure API Management released a new version that changes the OpenAPI interpretation. This article dives into the potential impact on of the consumer experience of your APIs.
Update I (23-05-2018) - The Azure API Management team released a new version of the PowerShell cmdlet which now supports this new OpenAPI interpretation.
Update II (09-11-2018) - SwaggerOperation
is now available in the Swashbuckle.AspNetCore.Annotations
NuGet package instead of Swashbuckle.AspNetCore
.
Providing clean and well-documented APIs is a must. This allows your consumers to know what capabilities you provide, what they are for and what to expect.
This is where the OpenAPI specification, aka Swagger, comes in and defines how APIs should be defined across the industry, regardless of what technology is underneath it.
Recently, the Azure API Management team started releasing a new version of the product with some new features and some important changes in how they interpret the OpenAPI specification while importing/exporting them.
Before we dive into the changes to OpenAPI interpretation. I'd like to highlight that they've also added the capability to the display id of a specific operation. In the past, you still had to use the old Publisher portal for this but now you can find it via API > Operation > Frontend
.
Next to that, as of last Sunday, the old Publisher portal should be fully gone now, except for the analytics part.
OpenAPI Interpretation
The latest version also changes the way OpenAPI specifications are being interpreted and are now fully based on operation as defined by the OpenAPI spec.
Here are the changes in a nutshell:
- Id of the operation - Operation Id is based on
operation.operationId
, otherwise it is being generated similar toget-foo
- Name of the operation - Display name is based on
operation.summary
, otherwise it will useoperation.operationId
. If that is not specified, it will generate a name similar toGet - /foo
- Description of the operation - Description is based on
operation.description
I like this change because it makes sense, however, this can be a breaking change in your API documentation depending on how you achieved it in the past.
The reason for this is that before rolling out this change the interpretation was different:
- Id of the operation was a generated id
- Name of the operation was based on
operation.operationId
- Description of the operation was based on
operation.description
and falls back onoperation.summary
How I did it in the past
For all the projects I work on I use Swashbuckle because it's very easy to setup, use and ties into the standard XML documentation.
Here is an example of the documentation I provide for my health endpoint for Sello, which I use for demos.
/// <summary>
/// Gets the current health status of the API
/// </summary>
[HttpGet]
[Route("health")]
[SwaggerOperation("Get Health")]
[SwaggerResponse(HttpStatusCode.OK, "API is up & running")]
[SwaggerResponse(HttpStatusCode.InternalServerError, "API is not available")]
public IHttpActionResult Get()
{
return Ok();
}
As you notice, everything is right there and via the operation I specify what the operation is called and give a brief summary of what it does and what my consumers can expect as responses.
The OpenAPI specification that is generated will look like this:
{
"swagger": "2.0",
"info": { ... }
},
"host": "localhost:1337",
"schemes": ["https"],
"paths": {
"/api/v1/health": {
"get": {
"tags": ["Health"],
"summary": "Gets the current health status of the API",
"operationId": "Get Health",
"consumes": [],
"produces": ["application/json"],
"responses": {
"200": {
"description": "API is up & running"
},
"500": {
"description": "API is not available"
}
}
}
}
},
"definitions": { }
}
Once this is imported into Azure API Management the developer experience was similar to this:
However, this approach is no longer what I'd like to offer to my consumers because if you import it after the new version it looks like this:
How I'm doing it today
Aligning with the latest interpretation was fairly easy to be honest, instead of providing a description what the operation does via summary
I started using remarks
instead.
Next to that, I'm now using summary
to give the operation a friendly name and assigned a better operationId via SwaggerOperation
.
This is how it looks in code:
/// <summary>
/// Get Health
/// </summary>
/// <remarks>Gets the current health status of the API</remarks>
[HttpGet]
[Route("health")]
[SwaggerOperation("get-health")]
[SwaggerResponse(HttpStatusCode.OK, "API is up & running")]
[SwaggerResponse(HttpStatusCode.InternalServerError, "API is not available")]
public IHttpActionResult Get()
{
return Ok();
}
The new OpenAPI specification is compatible with the recent changes and will look like this:
{
"swagger": "2.0",
"info": { ... }
},
"host": "localhost:1337",
"schemes": ["https"],
"paths": {
"/api/v1/health": {
"get": {
"tags": ["Health"],
"summary": "Get Health",
"description": "Gets the current health status of the API",
"operationId": "get-health",
"consumes": [],
"produces": ["application/json"],
"responses": {
"200": {
"description": "API is up & running"
},
"500": {
"description": "API is not available"
}
}
}
}
},
"definitions": { }
}
Once this is imported the developer experience is maintained and looks similar to this:
When you go to the details of the new operation in the Azure portal, you will see that all our information is succesfully imported:
Conclusion
Azure API Management rolled out a change to the OpenAPI interpretation to provide more flexibility so you can define the operation id to use and align with the general specification.
This change is great, but it might have an impact on your current API documentation, similar to what I've experienced. With the above changes, you are good to go and your consumers will not even notice it.
Thanks for reading,
Tom.