Бөлісу құралы:


Начало работы с Microsoft.AspNetCore.OpenApi

Внимание

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

Пакет Microsoft.AspNetCore.OpenApi обеспечивает встроенную поддержку создания документов OpenAPI в ASP.NET Core. Пакет обладает следующими характеристиками:

Установка пакета

Установите пакет Microsoft.AspNetCore.OpenApi.

Выполните следующую команду из консоли диспетчер пакетов:

Install-Package Microsoft.AspNetCore.OpenApi -IncludePrerelease

Настройка создания документов OpenAPI

Следующий код:

  • Добавляет службы OpenAPI.
  • Включает конечную точку для просмотра документа OpenAPI в JSформате ON.
var builder = WebApplication.CreateBuilder();

builder.Services.AddOpenApi();

var app = builder.Build();

app.MapOpenApi();

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

app.Run();

Запустите приложение и перейдите к https://localhost:<port>/openapi/v1.json просмотру созданного документа OpenAPI.

Важность имен документов

Каждый документ OpenAPI в приложении имеет уникальное имя. Имя документа по умолчанию, зарегистрированного v1.

builder.Services.AddOpenApi(); // Document name is v1

Имя документа можно изменить, передав имя в качестве параметра вызову AddOpenApi .

builder.Services.AddOpenApi("internal"); // Document name is internal

Имя документа отображается в нескольких местах в реализации OpenAPI.

При получении созданного документа OpenAPI имя документа указывается в качестве documentName аргумента параметра в запросе. Следующие запросы разрешают v1 документы и internal документы.

GET http://localhost:5000/openapi/v1.json
GET http://localhost:5000/openapi/internal.json

Параметры настройки создания документов OpenAPI

В следующих разделах показано, как настроить создание документов OpenAPI.

Настройка версии OpenAPI созданного документа

По умолчанию создание документов OpenAPI создает документ, соответствующий спецификации OpenAPI версии 3.0. В следующем коде показано, как изменить версию документа OpenAPI по умолчанию:

builder.Services.AddOpenApi(options =>
{
    options.OpenApiVersion = OpenApiSpecVersion.OpenApi2_0;
});

Настройка маршрута конечной точки OpenAPI

По умолчанию конечная точка OpenAPI, зарегистрированная с помощью вызова, предоставляет MapOpenApi документ в конечной точке /openapi/{documentName}.json . В следующем коде показано, как настроить маршрут, в котором зарегистрирован документ OpenAPI:

app.MapOpenApi("/openapi/{documentName}/openapi.json");

Примечание. Возможно, но не рекомендуется удалить documentName параметр маршрута из маршрута конечной точки. documentName При удалении параметра маршрута из маршрута конечной точки платформа пытается разрешить имя документа из параметра запроса. Не предоставляя documentName маршрут или запрос, может привести к непредвиденному поведению.

Настройка конечной точки OpenAPI

Так как документ OpenAPI обслуживается через конечную точку обработчика маршрутов, любая настройка, доступная для стандартных минимальных конечных точек, доступна для конечной точки OpenAPI.

Настройка конечных точек OpenAPI с помощью метаданных конечной точки

В следующем списке показаны метаданные конечной точки, используемые для настройки созданного документа OpenAPI:

Дополнительные сведения о настройке созданного документа OpenAPI путем изменения метаданных конечной точки см. в статье "Использование OpenAPI" в приложениях API "Минимальный".

Ограничение доступа к документам OpenAPI авторизованным пользователям

Конечная точка OpenAPI не включает проверки авторизации по умолчанию. Однако можно ограничить доступ к документу OpenAPI. Например, в следующем коде доступ к документу OpenAPI ограничен теми, кто имеет tester роль:

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();

Созданный в кэше документ OpenAPI

Документ OpenAPI создается каждый раз, когда отправляется запрос к конечной точке OpenAPI. Восстановление позволяет преобразователям включать динамическое состояние приложения в свою работу. Например, повторное создание запроса с подробными сведениями о контексте HTTP. При необходимости документ OpenAPI можно кэшировать, чтобы избежать выполнения конвейера создания документов для каждого HTTP-запроса.

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();

Преобразователи документов OpenAPI

В этом разделе показано, как настроить документы OpenAPI с помощью преобразователей.

Настройка документов OpenAPI с помощью преобразователей

Преобразователи предоставляют API для изменения документа OpenAPI с пользовательскими настройками. Преобразователи полезны для таких сценариев:

  • Добавление параметров ко всем операциям в документе.
  • Изменение описания параметров или операций.
  • Добавление сведений верхнего уровня в документ OpenAPI.

Преобразователи делятся на две категории:

  • Преобразователи документов имеют доступ ко всему документу OpenAPI. Их можно использовать для внесения глобальных изменений в документ.
  • Преобразователи операций применяются к каждой отдельной операции. Каждая отдельная операция — это сочетание пути и метода HTTP. Их можно использовать для изменения параметров или ответов на конечных точках.

Преобразователи можно зарегистрировать в документе UseTransformer с помощью вызова OpenApiOptions объекта. В следующем фрагменте кода показаны различные способы регистрации преобразователей в документе:

  • Зарегистрируйте преобразователь документов с помощью делегата.
  • Зарегистрируйте преобразователь документов с помощью экземпляра IOpenApiDocumentTransformer.
  • Зарегистрируйте преобразователь документов с помощью активации IOpenApiDocumentTransformerDI.
  • Зарегистрируйте преобразователь операций с помощью делегата.
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder();

builder.Services.AddOpenApi(options =>
{
    options.UseTransformer((document, context, cancellationToken) 
                             => Task.CompletedTask);
    options.UseTransformer(new MyDocumentTransformer());
    options.UseTransformer<MyDocumentTransformer>();
    options.UseOperationTransformer((operation, context, cancellationToken)
                            => Task.CompletedTask);
});

var app = builder.Build();

app.MapOpenApi();

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

app.Run();

Порядок выполнения для преобразователей

Преобразователи выполняются в первом порядке на основе регистрации. В следующем фрагменте кода преобразователь документов имеет доступ к изменениям, внесенным преобразователем операций:

var builder = WebApplication.CreateBuilder();

builder.Services.AddOpenApi(options =>
{
    options.UseOperationTransformer((operation, context, cancellationToken)
                                     => Task.CompletedTask);
    options.UseTransformer((document, context, cancellationToken)
                                     => Task.CompletedTask);
});

var app = builder.Build();

app.MapOpenApi();

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

app.Run();

Использование преобразователей документов

Преобразователи документов имеют доступ к объекту контекста, который включает в себя:

  • Имя измененного документа.
  • Список ApiDescriptionGroups связанных с этим документом.
  • Используется IServiceProvider в создании документов.

Преобразователи документов также могут изменить созданный документ OpenAPI. В следующем примере показан преобразователь документов, который добавляет некоторые сведения об API в документ OpenAPI.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;

var builder = WebApplication.CreateBuilder();

builder.Services.AddOpenApi(options =>
{
    options.UseTransformer((document, context, cancellationToken) =>
    {
        document.Info = new()
        {
            Title = "Checkout API",
            Version = "v1",
            Description = "API for processing checkouts from cart."
        };
        return Task.CompletedTask;
    });
});

var app = builder.Build();

app.MapOpenApi();

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

app.Run();

Преобразователи документов, активируемые службой, могут использовать экземпляры из DI для изменения приложения. В следующем примере показан преобразователь документов, использующий IAuthenticationSchemeProvider службу из уровня проверки подлинности. Он проверяет, зарегистрированы ли в приложении схемы, связанные с носителями JWT, и добавляет их на верхний уровень документа OpenAPI:

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.AddOpenApi(options =>
{
    options.UseTransformer<BearerSecuritySchemeTransformer>();
});

var app = builder.Build();

app.MapOpenApi();

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

app.Run();

internal sealed class BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider) : IOpenApiDocumentTransformer
{
    public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
    {
        var authenticationSchemes = await authenticationSchemeProvider.GetAllSchemesAsync();
        if (authenticationSchemes.Any(authScheme => authScheme.Name == "Bearer"))
        {
            var requirements = new Dictionary<string, OpenApiSecurityScheme>
            {
                ["Bearer"] = new OpenApiSecurityScheme
                {
                    Type = SecuritySchemeType.Http,
                    Scheme = "bearer", // "bearer" refers to the header name here
                    In = ParameterLocation.Header,
                    BearerFormat = "Json Web Token"
                }
            };
            document.Components ??= new OpenApiComponents();
            document.Components.SecuritySchemes = requirements;
        }
    }
}

Преобразователи документов уникальны для экземпляра документа, с которым они связаны. В следующем примере преобразователь:

  • Регистрирует требования, связанные с проверкой подлинности, в документе internal .
  • Оставляет public документ не измененным.
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.AddOpenApi("internal", options =>
{
    options.UseTransformer<BearerSecuritySchemeTransformer>();
});
builder.Services.AddOpenApi("public");

var app = builder.Build();

app.MapOpenApi();

app.MapGet("/world", () => "Hello world!")
    .WithGroupName("internal");
app.MapGet("/", () => "Hello universe!")
    .WithGroupName("public");

app.Run();

internal sealed class BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider) : IOpenApiDocumentTransformer
{
    public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
    {
        var authenticationSchemes = await authenticationSchemeProvider.GetAllSchemesAsync();
        if (authenticationSchemes.Any(authScheme => authScheme.Name == "Bearer"))
        {
            // Add the security scheme at the document level
            var requirements = new Dictionary<string, OpenApiSecurityScheme>
            {
                ["Bearer"] = new OpenApiSecurityScheme
                {
                    Type = SecuritySchemeType.Http,
                    Scheme = "bearer", // "bearer" refers to the header name here
                    In = ParameterLocation.Header,
                    BearerFormat = "Json Web Token"
                }
            };
            document.Components ??= new OpenApiComponents();
            document.Components.SecuritySchemes = requirements;

            // Apply it as a requirement for all operations
            foreach (var operation in document.Paths.Values.SelectMany(path => path.Operations))
            {
                operation.Value.Security.Add(new OpenApiSecurityRequirement
                {
                    [new OpenApiSecurityScheme { Reference = new OpenApiReference { Id = "Bearer", Type = ReferenceType.SecurityScheme } }] = Array.Empty<string>()
                });
            }
        }
    }
}

Использование преобразователей операций

Операции — это уникальные сочетания путей и методов HTTP в документе OpenAPI. Преобразователи операций полезны при изменении:

  • Необходимо сделать каждую конечную точку в приложении или
  • Условно применяется к определенным маршрутам.

Преобразователи операций имеют доступ к объекту контекста, который содержит:

  • Имя документа, к которому принадлежит операция.
  • Объект ApiDescription, связанный с операцией.
  • Используется IServiceProvider в создании документов.

Например, следующий преобразователь операций добавляется 500 в виде кода состояния ответа, поддерживаемого всеми операциями в документе.

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.AddOpenApi(options =>
{
    options.UseOperationTransformer((operation, context, cancellationToken) =>
    {
        operation.Responses.Add("500", new OpenApiResponse { Description = "Internal server error" });
        return Task.CompletedTask;
    });
});

var app = builder.Build();

app.MapOpenApi();

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

app.Run();

Использование созданного документа OpenAPI

Документы OpenAPI могут подключаться к широкой экосистеме существующих средств для тестирования, документации и локальной разработки.

Использование пользовательского интерфейса Swagger для локального нерегламентированного тестирования

По умолчанию Microsoft.AspNetCore.OpenApi пакет не предоставляет встроенную поддержку визуализации или взаимодействия с документом OpenAPI. Популярные инструменты для визуализации или взаимодействия с документом OpenAPI включают пользовательский интерфейс Swagger и ReDoc. Пользовательский интерфейс Swagger и ReDoc можно интегрировать в приложение несколькими способами. Редакторы, такие как Visual Studio и VS Code, предлагают расширения и встроенные возможности для тестирования в документе OpenAPI.

Пакет Swashbuckle.AspNetCore.SwaggerUi предоставляет пакет веб-ресурсов пользовательского интерфейса Swagger для использования в приложениях. Этот пакет можно использовать для отрисовки пользовательского интерфейса для созданного документа. Чтобы настроить это, установите Swashbuckle.AspNetCore.SwaggerUi пакет.

Включите ПО промежуточного слоя swagger-ui со ссылкой на маршрут OpenAPI, зарегистрированный ранее. Чтобы ограничить раскрытие информации и уязвимость безопасности, включите только пользовательский интерфейс Swagger в средах разработки.

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.AddOpenApi();

var app = builder.Build();

app.MapOpenApi();
if (app.Environment.IsDevelopment())
{
    app.UseSwaggerUI(options =>
    {
        options.SwaggerEndpoint("/openapi/v1.json", "v1");
    });

}

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

app.Run();

Использование Scalar для интерактивной документации по API

Скаляр — это интерактивный интерфейс интерактивного документа с открытым кодом для OpenAPI. Скаляр может интегрироваться с конечной точкой OpenAPI, предоставляемой ASP.NET Core. Чтобы настроить Scalar, установите Scalar.AspNetCore пакет.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Scalar.AspNetCore;

var builder = WebApplication.CreateBuilder();

builder.Services.AddOpenApi();

var app = builder.Build();

app.MapOpenApi();

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

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

app.Run();

Lint создал документы OpenAPI с помощью Spectral

Spectral — это документ OpenAPI с открытым кодом. Spectral можно включить в сборку приложения, чтобы проверить качество созданных документов OpenAPI. Установите Spectral в соответствии с инструкциями по установке пакета.

Чтобы воспользоваться преимуществами Spectral, установите Microsoft.Extensions.ApiDescription.Server пакет, чтобы включить создание документов OpenAPI во время сборки.

Включите создание документов во время сборки, задав следующие свойства в файле приложения .csproj :

<PropertyGroup>
    <OpenApiDocumentsDirectory>$(MSBuildProjectDirectory)</OpenApiDocumentsDirectory>
    <OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>
</PropertyGroup>

Запустите dotnet build , чтобы создать документ.

dotnet build

.spectral.yml Создайте файл со следующим содержимым.

extends: ["spectral:oas"]

Запустите spectral lint созданный файл.

spectral lint WebMinOpenApi.json
...

The output shows any issues with the OpenAPI document.

```output
1:1  warning  oas3-api-servers       OpenAPI "servers" must be present and non-empty array.
3:10  warning  info-contact           Info object must have "contact" object.                        info
3:10  warning  info-description       Info "description" must be present and non-empty string.       info
9:13  warning  operation-description  Operation "description" must be present and non-empty string.  paths./.get
9:13  warning  operation-operationId  Operation must have "operationId".                             paths./.get

✖ 5 problems (0 errors, 5 warnings, 0 infos, 0 hints)