Skip to content

Add property to OpenApiOptions to allow dynamic OpenAPI version selection #62984

@martincostello

Description

@martincostello

Background and Motivation

While working on #62193 (comment), I noticed that it isn't currently possible to dynamically select an OpenAPI document's version based on context provided by the user in an HTTP request, for example from a query string.

The version is currently defined in the options as part of registering the endpoint, so it isn't possible to change it other than when registering services, and as the options are registered as a singleton it isn't possible to mutate the options in the scope of an HTTP request to using something like IPostConfigureOptions<T> to change its value before the document is written.

await document.SerializeAsync(openApiWriter, documentOptions.OpenApiVersion, context.RequestAborted);

var options = endpoints.ServiceProvider.GetRequiredService<IOptionsMonitor<OpenApiOptions>>();

Proposed API

public OpenApiOptions
{
+   public Func<HttpContext, OpenApiSpecVersion?>? OpenApiVersionSelector { get; set; }
}

Then change the endpoint code to use it something like:

+ var openApiVersion = documentOptions.OpenApiVersionSelector?.Invoke(context) ?? documentOptions.OpenApiVersion;
- await document.SerializeAsync(openApiWriter, documentOptions.OpenApiVersion, context.RequestAborted);
+ await document.SerializeAsync(openApiWriter, openApiVersion, context.RequestAborted);

Usage Examples

builder.Services.AddOpenApi("v1", options =>
{
    options.OpenApiVersionSelector = (context) =>
    {
        if (context.Request.Query["version"] is { Count: 1 } version &&
            Enum.TryParse<OpenApiSpecVersion>(version, out var result))
        {
            return result;
        }

        return null;
    };
});
GET /openapi/v1.json?version=OpenApi3_0
{
  "openapi": "3.0.4"
}

Alternative Designs

public OpenApiOptions
{
+   public Func<HttpContext, Task<OpenApiSpecVersion?>>? OpenApiVersionSelector { get; set; }
}

Risks

None I can think of.

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-openapi

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions