Skip to content

Instantly share code, notes, and snippets.

@martincostello
Created July 31, 2024 18:58
Show Gist options
  • Save martincostello/c6d6167783b811d842163cdaf39a0987 to your computer and use it in GitHub Desktop.
Save martincostello/c6d6167783b811d842163cdaf39a0987 to your computer and use it in GitHub Desktop.
Generate YAML using Microsoft.AspNetCore.OpenApi
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