Permalink
Branch: master
Find file Copy path
f073498 Feb 3, 2019
1 contributor

Users who have contributed to this file

215 lines (165 sloc) 9.14 KB

Aliencube.AzureFunctions.Extensions.OpenApi

Build status

This enables Azure Functions to render Open API document and Swagger UI. The more details around the Swagger UI on Azure Functions can be found on this blog post.

NOTE: This extension supports both Open API 2.0 (aka Swagger) and Open API 3.0.1 spec.

Acknowledgement

Getting Started

In order to include an HTTP endpoint in the Open API document, use attribute classes (decorators) like:

[FunctionName(nameof(PostSample))]
[OpenApiOperation("add", "sample")]
[OpenApiRequestBody("application/json", typeof(SampleRequestModel))]
[OpenApiResponseBody(HttpStatusCode.OK, "application/json", typeof(SampleResponseModel))]
public static async Task<IActionResult> PostSample(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = "samples")] HttpRequest req,
    ILogger log)
{
    ...
}

Then, define another HTTP endpoint to render Swagger document:

[FunctionName(nameof(RenderSwaggerDocument))]
[OpenApiIgnore]
public static async Task<IActionResult> RenderSwaggerDocument(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = "swagger.json")] HttpRequest req,
    ILogger log)
{
    var settings = new AppSettings();
    var helper = new DocumentHelper();
    var document = new Document(helper);
    var result = await document.InitialiseDocument()
                               .AddMetadata(settings.OpenApiInfo)
                               .AddServer(req, settings.HttpSettings.RoutePrefix)
                               .Build(Assembly.GetExecutingAssembly())
                               .RenderAsync(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json)
                               .ConfigureAwait(false);
    var response = new ContentResult()
                       {
                           Content = result,
                           ContentType = "application/json",
                           StatusCode = (int)HttpStatusCode.OK
                       };

    return response;
}

In order to render Swagger UI, define another HTTP endpoint for it:

[FunctionName(nameof(RenderSwaggerUI))]
[OpenApiIgnore]
public static async Task<IActionResult> RenderSwaggerUI(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = "swagger/ui")] HttpRequest req,
    ILogger log)
{
    var settings = new AppSettings();
    var ui = new SwaggerUI();
    var result = await ui.AddMetadata(settings.OpenApiInfo)
                         .AddServer(req, settings.HttpSettings.RoutePrefix)
                         .BuildAsync(typeof(SwaggerUI).Assembly)
                         .RenderAsync("swagger.json", settings.SwaggerAuthKey)
                         .ConfigureAwait(false);
    var response = new ContentResult()
                       {
                           Content = result,
                           ContentType = "text/html",
                           StatusCode = (int)HttpStatusCode.OK
                       };

    return response;
}

App Settings

On either your local.settings.json or App Settings on Azure Functions instance, those details should be set up to render Open API metadata:

  • OpenApi__Info__Version: REQUIRED Version of Open API document. This is not the version of Open API spec. eg. 1.0.0
  • OpenApi__Info__Title: REQUIRED Title of Open API document. eg. Open API Sample on Azure Functions
  • OpenApi__Info__Description: Description of Open API document. eg. A sample API that runs on Azure Functions either 1.x or 2.x using Open API specification.
  • OpenApi__Info__TermsOfService: Terms of service URL. eg. https://github.com/aliencube/AzureFunctions.Extensions
  • OpenApi__Info__Contact__Name: Name of contact. eg. Aliencube Community
  • OpenApi__Info__Contact__Email: Email address for the contact. eg. no-reply@aliencube.org
  • OpenApi__Info__Contact__Url: Contact URL. eg. https://github.com/aliencube/AzureFunctions.Extensions/issues
  • OpenApi__Info__License__Name: REQUIRED License name. eg. MIT
  • OpenApi__Info__License__Url: License URL. eg. http://opensource.org/licenses/MIT
  • OpenApi__ApiKey: API Key of the endpoint that renders the Open API document.

Decorators

In order to render Open API document, this uses attribute classes (decorators).

NOTE: Not all Open API specs have been implemented.

OpenApiIgnoreAttribute

If there is any HTTP trigger that you want to exclude from the Open API document, use this decorator. Typically this is used for the endpoints that render Open API document and Swagger UI.

[FunctionName(nameof(RenderSwaggerDocument))]
[OpenApiIgnore] // This HTTP endpoint is excluded from the Open API document.
public static async Task<IActionResult> RenderSwaggerDocument(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = "swagger.{extension}")] HttpRequest req,
    string extension,
    ILogger log)
{
    ...
}

OpenApiOperationAttribute

This decorator implements a part of Operation object spec.

[FunctionName(nameof(GetSample))]
[OpenApiOperation("list", "sample")] // This defines the operation ID and tags.
...
public static async Task<IActionResult> GetSample(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "samples")] HttpRequest req,
    ILogger log)
{
    ...
}

If the operation ID is omitted, a combination of function name and verb is considered as the operation ID.

OpenApiParameterAttribute

This decorator implements the Parameter object spec.

[FunctionName(nameof(GetSample))]
// This defines the parameter name, location and type.
[OpenApiParameter("name", In = ParameterLocation.Query, Required = true, Type = typeof(string))]
...
public static async Task<IActionResult> GetSample(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "samples")] HttpRequest req,
    ILogger log)
{
    ...
}
  • Name: is the name of the parameter.
  • Description: is the description of the parameter.
  • In: identifies where the parameter is located – header, path, query or cookie. Default value is path.
  • Required: indicates whether the parameter is required or not. Default value is false.
  • Type: defines the parameter type. Default value is typeof(string).

OpenApiRequestBodyAttribute

This decorator implements the Request Body object spec.

[FunctionName(nameof(PostSample))]
[OpenApiRequestBody("application/json", typeof(SampleRequestModel))]
...
public static async Task<IActionResult> PostSample(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = "samples")] HttpRequest req,
    ILogger log)
{
    ...
}
  • ContentType: defines the content type of the request body payload. eg) application/json or text/xml
  • BodyType: defines the type of the request payload.
  • Description: is the description of the request body payload.

OpenApiResponseBodyAttribute

This decorator implements the Response object spec.

[FunctionName(nameof(PostSample))]
[OpenApiResponseBody(HttpStatusCode.OK, "application/json", typeof(SampleResponseModel))]
...
public static async Task<IActionResult> PostSample(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = "samples")] HttpRequest req,
    ILogger log)
{
    ...
}
  • StatusCode: defines the HTTP status code. eg) HttpStatusCode.OK
  • ContentType: defines the content type of the response body payload. eg) application/json or text/xml
  • BodyType: defines the type of the response payload.
  • Description: is the description of the response body payload.