Created
July 31, 2024 18:58
-
-
Save martincostello/c6d6167783b811d842163cdaf39a0987 to your computer and use it in GitHub Desktop.
Generate YAML using Microsoft.AspNetCore.OpenApi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Diagnostics.CodeAnalysis; | |
using Microsoft.Extensions.Options; | |
using Microsoft.OpenApi.Extensions; | |
using Microsoft.OpenApi.Models; | |
using Microsoft.OpenApi.Writers; | |
namespace Microsoft.AspNetCore.OpenApi; | |
public static class OpenApiYamlEndpoint | |
{ | |
public static IEndpointConventionBuilder MapOpenApiYaml( | |
this IEndpointRouteBuilder endpoints, | |
[StringSyntax("Route")] string pattern = "/openapi/{documentName}.yml") | |
{ | |
var type = Type.GetType("Microsoft.AspNetCore.OpenApi.OpenApiDocumentService, Microsoft.AspNetCore.OpenApi"); | |
var methodInfo = type!.GetMethod("GetOpenApiDocumentAsync")!; | |
var options = endpoints.ServiceProvider.GetRequiredService<IOptionsMonitor<OpenApiOptions>>(); | |
return endpoints.MapGet(pattern, async (HttpContext context, string documentName = "v1") => | |
{ | |
object? documentService = context.RequestServices.GetRequiredKeyedService(type!, documentName); | |
if (documentService is null) | |
{ | |
context.Response.StatusCode = StatusCodes.Status404NotFound; | |
context.Response.ContentType = "text/plain;charset=utf-8"; | |
await context.Response.WriteAsync($"No OpenAPI document with the name '{documentName}' was found."); | |
} | |
else | |
{ | |
var document = await GetOpenApiDocumentAsync(documentService, context.RequestAborted); | |
var documentOptions = options.Get(documentName); | |
using var memory = new MemoryStream(); | |
using var streamWriter = new StreamWriter(memory); | |
var yamlWriter = new OpenApiYamlWriter(streamWriter); | |
document.Serialize(yamlWriter, documentOptions.OpenApiVersion); | |
context.Response.ContentType = "application/yaml"; | |
await context.Response.BodyWriter.WriteAsync(memory.ToArray(), context.RequestAborted); | |
await context.Response.BodyWriter.FlushAsync(context.RequestAborted); | |
} | |
}).ExcludeFromDescription(); | |
async Task<OpenApiDocument> GetOpenApiDocumentAsync(object documentService, CancellationToken cancellationToken) | |
{ | |
var result = (Task<OpenApiDocument>)methodInfo.Invoke(documentService, [cancellationToken])!; | |
return await result; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment