|
|
@@ -14,6 +14,7 @@ using System.Reflection;
|
|
|
using Microsoft.AspNetCore.Hosting.Server;
|
|
|
using Microsoft.AspNetCore.Hosting.Server.Features;
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
+using Microsoft.AspNetCore.Http.Extensions;
|
|
|
using Microsoft.AspNetCore.Http.Metadata;
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
|
|
@@ -56,7 +57,7 @@ internal sealed class OpenApiDocumentService(
|
|
|
internal bool TryGetCachedOperationTransformerContext(string descriptionId, [NotNullWhen(true)] out OpenApiOperationTransformerContext? context)
|
|
|
=> _operationTransformerContextCache.TryGetValue(descriptionId, out context);
|
|
|
|
|
|
- public async Task<OpenApiDocument> GetOpenApiDocumentAsync(IServiceProvider scopedServiceProvider, CancellationToken cancellationToken = default)
|
|
|
+ public async Task<OpenApiDocument> GetOpenApiDocumentAsync(IServiceProvider scopedServiceProvider, HttpRequest? httpRequest = null, CancellationToken cancellationToken = default)
|
|
|
{
|
|
|
// Schema and operation transformers are scoped per-request and can be
|
|
|
// pre-allocated to hold the same number of transformers as the associated
|
|
|
@@ -71,7 +72,7 @@ internal sealed class OpenApiDocumentService(
|
|
|
var document = new OpenApiDocument
|
|
|
{
|
|
|
Info = GetOpenApiInfo(),
|
|
|
- Servers = GetOpenApiServers()
|
|
|
+ Servers = GetOpenApiServers(httpRequest)
|
|
|
};
|
|
|
document.Paths = await GetOpenApiPathsAsync(document, scopedServiceProvider, operationTransformers, schemaTransformers, cancellationToken);
|
|
|
document.Tags = document.Tags?.Distinct(OpenApiTagComparer.Instance).ToList();
|
|
|
@@ -198,12 +199,26 @@ internal sealed class OpenApiDocumentService(
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- internal List<OpenApiServer> GetOpenApiServers()
|
|
|
+ // Resolve server URL from the request to handle reverse proxies.
|
|
|
+ // If there is active request object, assume a development environment and use the server addresses.
|
|
|
+ internal List<OpenApiServer> GetOpenApiServers(HttpRequest? httpRequest = null)
|
|
|
+ {
|
|
|
+ if (httpRequest is not null)
|
|
|
+ {
|
|
|
+ var serverUrl = UriHelper.BuildAbsolute(httpRequest.Scheme, httpRequest.Host, httpRequest.PathBase);
|
|
|
+ return [new OpenApiServer { Url = serverUrl }];
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return GetDevelopmentOpenApiServers();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private List<OpenApiServer> GetDevelopmentOpenApiServers()
|
|
|
{
|
|
|
if (hostEnvironment.IsDevelopment() &&
|
|
|
server?.Features.Get<IServerAddressesFeature>()?.Addresses is { Count: > 0 } addresses)
|
|
|
{
|
|
|
- return addresses.Select(address => new OpenApiServer { Url = address }).ToList();
|
|
|
+ return [.. addresses.Select(address => new OpenApiServer { Url = address })];
|
|
|
}
|
|
|
return [];
|
|
|
}
|