Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static IEndpointConventionBuilder MapOpenApi(this IEndpointRouteBuilder e
else
{
var document = await documentService.GetOpenApiDocumentAsync(context.RequestServices, context.RequestAborted);
var documentOptions = options.Get(documentName);
var documentOptions = options.Get(lowercasedDocumentName);
using var output = MemoryBufferWriter.Get();
using var writer = Utf8BufferTextWriter.Get(output);
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Readers;
using System.Text;
using Microsoft.OpenApi;

public class OpenApiEndpointRouteBuilderExtensionsTests : OpenApiDocumentServiceTestBase
{
Expand Down Expand Up @@ -156,6 +157,40 @@ public async Task MapOpenApi_ReturnsDocumentWhenPathIsCaseSensitive(string regis
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode);
}

[Fact]
public async Task MapOpenApi_ShouldRetrieveOptionsInACaseInsensitiveManner()
{
// Arrange
var hostEnvironment = new HostEnvironment() { ApplicationName = nameof(OpenApiEndpointRouteBuilderExtensionsTests) };
var serviceProviderIsService = new ServiceProviderIsService();
var serviceProvider = CreateServiceProvider("casesensitive", OpenApiSpecVersion.OpenApi2_0);
var builder = new DefaultEndpointRouteBuilder(new ApplicationBuilder(serviceProvider));
builder.MapOpenApi("/openapi/{documentName}.json");
var context = new DefaultHttpContext();
var responseBodyStream = new MemoryStream();
context.Response.Body = responseBodyStream;
context.RequestServices = serviceProvider;
context.Request.RouteValues.Add("documentName", "CaseSensitive");
var endpoint = builder.DataSources.First().Endpoints[0];

// Act
var requestDelegate = endpoint.RequestDelegate;
await requestDelegate(context);

// Assert
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode);
var responseString = Encoding.UTF8.GetString(responseBodyStream.ToArray());

// When we receive an OpenAPI document, we use an OptionsMonitor to retrieve named options that equal the requested document name.
// This is case-sensitive. If the document doesn't exist, the options monitor return a default instance, in which the OpenAPI version is set to v3.
// By setting up a v2 document on the "casesensitive" route and requesting it on "CaseSensitive",
// we can test that the we've configured the options monitor to retrieve the options in a case-insensitive manner.
// If it is case-sensitive, it would return a default instance with OpenAPI version v3, which would cause this test to fail!
// However, if it would return the v2 instance, the test would pass!
// For more info, see OpenApiEndpointRouteBuilderExtensions.cs
Assert.StartsWith("{\n \"swagger\": \"2.0\"", responseString);
}

[Theory]
[InlineData("/openapi.json", "application/json;charset=utf-8", false)]
[InlineData("/openapi.yaml", "text/plain+yaml;charset=utf-8", true)]
Expand Down Expand Up @@ -201,7 +236,7 @@ private static void ValidateOpenApiDocument(MemoryStream documentStream, Action<
action(document);
}

private static IServiceProvider CreateServiceProvider(string documentName = Microsoft.AspNetCore.OpenApi.OpenApiConstants.DefaultDocumentName)
private static IServiceProvider CreateServiceProvider(string documentName = Microsoft.AspNetCore.OpenApi.OpenApiConstants.DefaultDocumentName, OpenApiSpecVersion openApiSpecVersion = OpenApiSpecVersion.OpenApi3_0)
{
var hostEnvironment = new HostEnvironment() { ApplicationName = nameof(OpenApiEndpointRouteBuilderExtensionsTests) };
var serviceProviderIsService = new ServiceProviderIsService();
Expand All @@ -210,7 +245,7 @@ private static IServiceProvider CreateServiceProvider(string documentName = Micr
.AddSingleton<IHostEnvironment>(hostEnvironment)
.AddSingleton(CreateApiDescriptionGroupCollectionProvider())
.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance)
.AddOpenApi(documentName)
.AddOpenApi(documentName, x => x.OpenApiVersion = openApiSpecVersion)
.BuildServiceProvider();
return serviceProvider;
}
Expand Down
Loading