Skip to content

Commit

Permalink
Remove reflection-based JSON serialization from SwaggerUIMiddleware
Browse files Browse the repository at this point in the history
  • Loading branch information
VMelnalksnis committed Apr 15, 2024
1 parent 0108842 commit 0bdd165
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 15 deletions.
38 changes: 23 additions & 15 deletions src/Swashbuckle.AspNetCore.SwaggerUI/SwaggerUIMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Reflection;
using System.Reflection;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Text;
Expand All @@ -14,7 +13,6 @@
using Microsoft.Extensions.Options;
using Microsoft.Extensions.FileProviders;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.AspNetCore.Http.Extensions;
using System.Linq;

#if NETSTANDARD2_0
Expand All @@ -30,6 +28,9 @@ public class SwaggerUIMiddleware
private readonly SwaggerUIOptions _options;
private readonly StaticFileMiddleware _staticFileMiddleware;
private readonly JsonSerializerOptions _jsonSerializerOptions;
#if NET6_0_OR_GREATER
private readonly SwaggerUISerializerContext _context;
#endif

public SwaggerUIMiddleware(
RequestDelegate next,
Expand All @@ -49,6 +50,10 @@ public SwaggerUIMiddleware(
#endif
_jsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
_jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase, false));

#if NET6_0_OR_GREATER
_context = new(_jsonSerializerOptions);
#endif
}

public async Task Invoke(HttpContext httpContext)
Expand All @@ -57,7 +62,7 @@ public async Task Invoke(HttpContext httpContext)
var path = httpContext.Request.Path.Value;

// If the RoutePrefix is requested (with or without trailing slash), redirect to index URL
if (httpMethod == "GET" && Regex.IsMatch(path, $"^/?{Regex.Escape(_options.RoutePrefix)}/?$", RegexOptions.IgnoreCase))
if (httpMethod == "GET" && Regex.IsMatch(path, $"^/?{Regex.Escape(_options.RoutePrefix)}/?$", RegexOptions.IgnoreCase))
{
// Use relative redirect to support proxy environments
var relativeIndexUrl = string.IsNullOrEmpty(path) || path.EndsWith("/")
Expand All @@ -68,7 +73,7 @@ public async Task Invoke(HttpContext httpContext)
return;
}

if (httpMethod == "GET" && Regex.IsMatch(path, $"^/{Regex.Escape(_options.RoutePrefix)}/?index.html$", RegexOptions.IgnoreCase))
if (httpMethod == "GET" && Regex.IsMatch(path, $"^/{Regex.Escape(_options.RoutePrefix)}/?index.html$", RegexOptions.IgnoreCase))
{
await RespondWithIndexHtml(httpContext.Response);
return;
Expand Down Expand Up @@ -118,16 +123,19 @@ private async Task RespondWithIndexHtml(HttpResponse response)
}
}

private IDictionary<string, string> GetIndexArguments()
private IDictionary<string, string> GetIndexArguments() => new Dictionary<string, string>
{
return new Dictionary<string, string>()
{
{ "%(DocumentTitle)", _options.DocumentTitle },
{ "%(HeadContent)", _options.HeadContent },
{ "%(ConfigObject)", JsonSerializer.Serialize(_options.ConfigObject, _jsonSerializerOptions) },
{ "%(OAuthConfigObject)", JsonSerializer.Serialize(_options.OAuthConfigObject, _jsonSerializerOptions) },
{ "%(Interceptors)", JsonSerializer.Serialize(_options.Interceptors) },
};
}
{ "%(DocumentTitle)", _options.DocumentTitle },
{ "%(HeadContent)", _options.HeadContent },
#if NET6_0_OR_GREATER
{ "%(ConfigObject)", JsonSerializer.Serialize(_options.ConfigObject, _context.ConfigObject) },
{ "%(OAuthConfigObject)", JsonSerializer.Serialize(_options.OAuthConfigObject, _context.OAuthConfigObject) },
{ "%(Interceptors)", JsonSerializer.Serialize(_options.Interceptors, _context.InterceptorFunctions) },
#else
{ "%(ConfigObject)", JsonSerializer.Serialize(_options.ConfigObject, _jsonSerializerOptions) },
{ "%(OAuthConfigObject)", JsonSerializer.Serialize(_options.OAuthConfigObject, _jsonSerializerOptions) },
{ "%(Interceptors)", JsonSerializer.Serialize(_options.Interceptors) },
#endif
};
}
}
14 changes: 14 additions & 0 deletions src/Swashbuckle.AspNetCore.SwaggerUI/SwaggerUISerializerContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#if NET6_0_OR_GREATER
using System.Text.Json.Serialization;

namespace Swashbuckle.AspNetCore.SwaggerUI
{
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Default)]
[JsonSerializable(typeof(ConfigObject))]
[JsonSerializable(typeof(OAuthConfigObject))]
[JsonSerializable(typeof(InterceptorFunctions))]
internal sealed partial class SwaggerUISerializerContext : JsonSerializerContext
{
}
}
#endif

0 comments on commit 0bdd165

Please sign in to comment.