Skip to content

Commit

Permalink
Add content on endpoint customization and Scalar docs (#32572)
Browse files Browse the repository at this point in the history
  • Loading branch information
captainsafia committed May 13, 2024
1 parent f209e70 commit a711f86
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#define SWAGGERUI
#define OPENAPIWITHSCALAR

#if DEFAULT
using Microsoft.AspNetCore.OpenApi;
Expand Down Expand Up @@ -216,8 +216,7 @@ public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransf
}
}
}

// </snippet_multidoc_operationtransformer2>
// </snippet_multidoc_operationtransformer1>
#endif

#if SWAGGERUI
Expand Down Expand Up @@ -249,3 +248,118 @@ public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransf
app.Run();
// </snippet_swaggerui>
#endif

#if MAPOPENAPIWITHAUTH
// <snippet_mapopenapiwithauth>
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder();

builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization(o =>
{
o.AddPolicy("ApiTesterPolicy", b => b.RequireRole("tester"));
});
builder.Services.AddOpenApi();

var app = builder.Build();

app.MapOpenApi()
.RequireAuthorization("ApiTesterPolicy");

app.MapGet("/", () => "Hello world!");

app.Run();
// </snippet_mapopenapiwithauth>
#endif

#if MAPOPENAPIWITHCACHING
// <snippet_mapopenapiwithcaching>
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder();

builder.Services.AddOutputCache(options =>
{
options.AddBasePolicy(policy => policy.Expire(TimeSpan.FromMinutes(10)));
});
builder.Services.AddOpenApi();

var app = builder.Build();

app.UseOutputCache();

app.MapOpenApi()
.CacheOutput();

app.MapGet("/", () => "Hello world!");

app.Run();
// </snippet_mapopenapiwithcaching>
#endif

#if OPENAPIWITHSCALAR
// <snippet_openapiwithscalar>
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder();

builder.Services.AddOpenApi();

var app = builder.Build();

app.MapOpenApi();

if (app.Environment.IsDevelopment())
{
app.MapScalarUi();
}

app.MapGet("/", () => "Hello world!");

app.Run();

static class OpenApiEndpointRouteBuilderExtensions
{
public static IEndpointConventionBuilder MapScalarUi(this IEndpointRouteBuilder endpoints)
{
return endpoints.MapGet("/scalar/{documentName}", (string documentName) => Results.Content($$"""
<!doctype html>
<html>
<head>
<title>Scalar API Reference -- {{documentName}}</title>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1" />
</head>
<body>
<script
id="api-reference"
data-url="/openapi/{{documentName}}.json"></script>
<script>
var configuration = {
theme: 'purple',
}
document.getElementById('api-reference').dataset.configuration =
JSON.stringify(configuration)
</script>
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
</body>
</html>
""", "text/html")).ExcludeFromDescription();
}
}
// </snippet_openapiwithscalar>
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
}
}
},
"x-aspnetcore-id": "12a849de-622a-4fe0-a605-a5ea17254453"
"x-aspnetcore-id": "c231c3b9-492e-4f0b-9a4e-8c815eb08db6"
}
}
},
Expand Down
22 changes: 22 additions & 0 deletions aspnetcore/fundamentals/minimal-apis/aspnetcore-openapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,22 @@ app.MapOpenApi("/openapi/{documentName}/openapi.json");

> Note: It's possible, but not recommended, to remove the `documentName` route parameter from the endpoint route. In this case, the framework will attempt to resolve the document name from the query parameter. Not providing the `documentName` in either the route or query can result in unexpected behavior.
### Customizing the OpenAPI endpoint

Because the OpenAPI document is served via a route handler endpoint, any customization that is available to standard minimal endpoints is available to the OpenAPI endpoint.

#### Limiting access to OpenAPI document to authorized users

The OpenAPI endpoint is not does not enable any authorization checks by default. However, it's possible to limit access to the OpenAPI document to those with the `tester` scope using the following configuration:

[!code-csharp[](~/fundamentals/minimal-apis/9.0-samples/WebMinOpenApi/Program.cs?name=snippet_mapopenapiwithauth)]

#### Caching generated OpenAPI document

The OpenAPI document is re-generated every time a request to the OpenAPI endpoint is sent. This behavior enables the use of transformers that dynamically access application state, like information in the HTTP context, as part of their implementation. When applicable, the OpenAPI document can be cached to avoid executing the document generation pipeline on each HTTP request.

[!code-csharp[](~/fundamentals/minimal-apis/9.0-samples/WebMinOpenApi/Program.cs?name=snippet_mapopenapiwithcaching)]

## Customizing OpenAPI documents with transformers

Transformers provide an API for modifying the OpenAPI document that is generated by the framework with user-defined customizations. Transformers are useful for scenarios like adding parameters to all operations in a document, modifying descriptions for parameters or operations, and adding top-level information to the OpenAPI document.
Expand Down Expand Up @@ -241,6 +257,12 @@ Enable the swagger-ui middleware with a reference to the OpenAPI route registere

[!code-csharp[](~/fundamentals/minimal-apis/9.0-samples/WebMinOpenApi/Program.cs?name=snippet_swaggerui)]

### Using Scalar for interactive API documentation

[Scalar](https://scalar.com/) is an open-source interactive document UI for OpenAPI. Scalar can integrate with the OpenAPI endpoint provided by ASP.NET Core.

[!code-csharp[](~/fundamentals/minimal-apis/9.0-samples/WebMinOpenApi/Program.cs?name=snippet_openapiwithscalar)]

### Linting generated OpenAPI documents with Spectral

Spectral is an open-source OpenAPI document linter. Spectral can be incorporated into your application build to verify the quality of generated OpenAPI documents. Install Spectral according to the [package installation directions](https://github.com/stoplightio/spectral#-installation).
Expand Down

0 comments on commit a711f86

Please sign in to comment.