swagger extensions
parent
38be5dedaf
commit
c2c81a7000
|
@ -1,8 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace NDB.Extensions.Swagger
|
|
||||||
{
|
|
||||||
public class Class1
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace NDB.Extensions.Swagger.Constants
|
||||||
|
{
|
||||||
|
public enum AuthorizationType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Basic
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using Microsoft.OpenApi.Models;
|
||||||
using System.Collections.Generic;
|
using NDB.Application.DataContracts;
|
||||||
using System.Text;
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace NDB.Extensions.Swagger.Filters
|
namespace NDB.Extensions.Swagger.Filters
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace NDB.Extensions.Swagger.Filters
|
||||||
|
{
|
||||||
|
public class PathParamsOperationFilter : IOperationFilter
|
||||||
|
{
|
||||||
|
public void Apply(OpenApiOperation operation, OperationFilterContext context)
|
||||||
|
{
|
||||||
|
const string paramCaptureGroup = "param";
|
||||||
|
|
||||||
|
foreach (var parameter in operation.Parameters.ToList())
|
||||||
|
{
|
||||||
|
if (parameter.Name.ToLowerInvariant().StartsWith("metadata"))
|
||||||
|
{
|
||||||
|
operation.Parameters.Remove(parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var openApiPathParameters = operation.Parameters.Where(param => param.In == ParameterLocation.Path).ToList();
|
||||||
|
var pathParamRegEx = $@"\{{(?<{paramCaptureGroup}>[^\}}]+)\}}";
|
||||||
|
|
||||||
|
if (openApiPathParameters.Any())
|
||||||
|
{
|
||||||
|
var pathParameterMatches = Regex.Matches(context.ApiDescription.RelativePath, pathParamRegEx, RegexOptions.Compiled);
|
||||||
|
var pathParameters = pathParameterMatches.Cast<Match>().Select(x => x.Groups[paramCaptureGroup].Value);
|
||||||
|
|
||||||
|
foreach (var openApiPathParameter in openApiPathParameters)
|
||||||
|
{
|
||||||
|
var correspondingPathParameter = pathParameters.FirstOrDefault(x =>
|
||||||
|
string.Equals(x, openApiPathParameter.Name, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
|
||||||
|
if (correspondingPathParameter != null)
|
||||||
|
openApiPathParameter.Name = correspondingPathParameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,4 +4,9 @@
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="NDB.Application.DataContracts" Version="1.0.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace NDB.Extensions.Swagger.ReverseProxy
|
||||||
|
{
|
||||||
|
public static class ReverseProxyHelper
|
||||||
|
{
|
||||||
|
public static (string host, string basePath, string scheme) GetUrlComponents(HttpRequest request)
|
||||||
|
{
|
||||||
|
var host = ExtractHost(request);
|
||||||
|
var basePath = ExtractBasePath(request);
|
||||||
|
var scheme = ExtractScheme(request);
|
||||||
|
|
||||||
|
return (host, basePath, scheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExtractHost(HttpRequest request)
|
||||||
|
{
|
||||||
|
if (request.Headers.ContainsKey("X-Forwarded-Host"))
|
||||||
|
return request.Headers["X-Forwarded-Host"].First();
|
||||||
|
|
||||||
|
return request.Host.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExtractBasePath(HttpRequest request)
|
||||||
|
{
|
||||||
|
if (request.Headers.ContainsKey("X-Forwarded-PathBase"))
|
||||||
|
return request.Headers["X-Forwarded-PathBase"].First();
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExtractScheme(HttpRequest request)
|
||||||
|
{
|
||||||
|
return request.Headers["X-Forwarded-Proto"].FirstOrDefault() ?? request.Scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using NDB.Extensions.Swagger.Constants;
|
||||||
|
using NDB.Extensions.Swagger.Filters;
|
||||||
|
using NDB.Extensions.Swagger.ReverseProxy;
|
||||||
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace NDB.Extensions.Swagger
|
||||||
|
{
|
||||||
|
public static class SwaggerExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddSwagger(this IServiceCollection services, string title, AuthorizationType authorizationType = AuthorizationType.Basic)
|
||||||
|
{
|
||||||
|
services.AddSwaggerGen(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerDoc("v1",
|
||||||
|
new OpenApiInfo
|
||||||
|
{
|
||||||
|
Title = title,
|
||||||
|
Version = "v1"
|
||||||
|
});
|
||||||
|
|
||||||
|
c.SetAuthorization(authorizationType);
|
||||||
|
c.OperationFilter<PathParamsOperationFilter>();
|
||||||
|
c.SchemaFilter<DtoSchemaFilter>();
|
||||||
|
c.CustomSchemaIds(type => type.ToString());
|
||||||
|
});
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetAuthorization(this SwaggerGenOptions options, AuthorizationType authorizationType)
|
||||||
|
{
|
||||||
|
switch (authorizationType)
|
||||||
|
{
|
||||||
|
case AuthorizationType.None:
|
||||||
|
return;
|
||||||
|
|
||||||
|
case AuthorizationType.Basic:
|
||||||
|
options.AddSecurityDefinition("Basic",
|
||||||
|
new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Description = @"JWT Authorization header using the Basic scheme. Enter 'Basic' [space] and then your token in the text input below. Example: 'Basic 12345abcdef'",
|
||||||
|
Name = "Authorization",
|
||||||
|
Scheme = "Basic",
|
||||||
|
Type = SecuritySchemeType.ApiKey
|
||||||
|
});
|
||||||
|
|
||||||
|
options.AddSecurityRequirement(new OpenApiSecurityRequirement()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Reference = new OpenApiReference
|
||||||
|
{
|
||||||
|
Type = ReferenceType.SecurityScheme,
|
||||||
|
Id = "Basic"
|
||||||
|
},
|
||||||
|
Scheme = "Basic",
|
||||||
|
Name = "Authorization",
|
||||||
|
In = ParameterLocation.Header
|
||||||
|
},
|
||||||
|
new List<string>()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException($"Swagger extensions: Authorization type '{authorizationType}' is not implemented.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IApplicationBuilder ConfigureSwagger(this IApplicationBuilder applicationBuilder, string endpointName)
|
||||||
|
{
|
||||||
|
applicationBuilder.UseSwagger(c =>
|
||||||
|
{
|
||||||
|
c.PreSerializeFilters.Add((swagger, httpRequest) =>
|
||||||
|
{
|
||||||
|
var (host, basePath, scheme) = ReverseProxyHelper.GetUrlComponents(httpRequest);
|
||||||
|
|
||||||
|
swagger.Servers = new List<OpenApiServer>
|
||||||
|
{
|
||||||
|
new OpenApiServer {Url = $"{scheme}://{host}{basePath}"}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
c.RouteTemplate = "swagger/{documentName}/swagger.json";
|
||||||
|
});
|
||||||
|
|
||||||
|
applicationBuilder.UseSwaggerUI(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerEndpoint("v1/swagger.json", endpointName);
|
||||||
|
c.RoutePrefix = $"swagger";
|
||||||
|
});
|
||||||
|
|
||||||
|
return applicationBuilder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue