Merge pull request #2925 from crobibero/redoc

Enhance Swagger Generation
This commit is contained in:
Bond-009 2020-05-03 19:36:42 +02:00 committed by GitHub
commit f2bace2a07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 12 deletions

View File

@ -1,5 +1,7 @@
using System; using System;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Browser namespace Emby.Server.Implementations.Browser
@ -24,7 +26,7 @@ namespace Emby.Server.Implementations.Browser
/// <param name="appHost">The app host.</param> /// <param name="appHost">The app host.</param>
public static void OpenSwaggerPage(IServerApplicationHost appHost) public static void OpenSwaggerPage(IServerApplicationHost appHost)
{ {
TryOpenUrl(appHost, "/swagger/index.html"); TryOpenUrl(appHost, "/api-docs/swagger");
} }
/// <summary> /// <summary>

View File

@ -10,7 +10,8 @@
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="3.1.3" /> <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="3.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="5.3.3" />
<PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="5.3.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,4 +1,4 @@
using Jellyfin.Server.Middleware; using MediaBrowser.Controller.Configuration;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
namespace Jellyfin.Server.Extensions namespace Jellyfin.Server.Extensions
@ -12,16 +12,38 @@ namespace Jellyfin.Server.Extensions
/// Adds swagger and swagger UI to the application pipeline. /// Adds swagger and swagger UI to the application pipeline.
/// </summary> /// </summary>
/// <param name="applicationBuilder">The application builder.</param> /// <param name="applicationBuilder">The application builder.</param>
/// <param name="serverConfigurationManager">The server configuration.</param>
/// <returns>The updated application builder.</returns> /// <returns>The updated application builder.</returns>
public static IApplicationBuilder UseJellyfinApiSwagger(this IApplicationBuilder applicationBuilder) public static IApplicationBuilder UseJellyfinApiSwagger(
this IApplicationBuilder applicationBuilder,
IServerConfigurationManager serverConfigurationManager)
{ {
applicationBuilder.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint. // specifying the Swagger JSON endpoint.
return applicationBuilder.UseSwaggerUI(c =>
var baseUrl = serverConfigurationManager.Configuration.BaseUrl.Trim('/');
if (!string.IsNullOrEmpty(baseUrl))
{ {
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Jellyfin API V1"); baseUrl += '/';
}
return applicationBuilder
.UseSwagger(c =>
{
// Custom path requires {documentName}, SwaggerDoc documentName is 'api-docs'
c.RouteTemplate = $"/{baseUrl}{{documentName}}/openapi.json";
})
.UseSwaggerUI(c =>
{
c.DocumentTitle = "Jellyfin API";
c.SwaggerEndpoint($"/{baseUrl}api-docs/openapi.json", "Jellyfin API");
c.RoutePrefix = $"{baseUrl}api-docs/swagger";
})
.UseReDoc(c =>
{
c.DocumentTitle = "Jellyfin API";
c.SpecUrl($"/{baseUrl}api-docs/openapi.json");
c.RoutePrefix = $"{baseUrl}api-docs/redoc";
}); });
} }
} }

View File

@ -1,3 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json.Serialization;
using Jellyfin.Api; using Jellyfin.Api;
using Jellyfin.Api.Auth; using Jellyfin.Api.Auth;
using Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy; using Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy;
@ -91,7 +96,22 @@ namespace Jellyfin.Server.Extensions
{ {
return serviceCollection.AddSwaggerGen(c => return serviceCollection.AddSwaggerGen(c =>
{ {
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Jellyfin API", Version = "v1" }); c.SwaggerDoc("api-docs", new OpenApiInfo { Title = "Jellyfin API" });
// Add all xml doc files to swagger generator.
var xmlFiles = Directory.GetFiles(
AppContext.BaseDirectory,
"*.xml",
SearchOption.TopDirectoryOnly);
foreach (var xmlFile in xmlFiles)
{
c.IncludeXmlComments(xmlFile);
}
// Order actions by route path, then by http method.
c.OrderActionsBy(description =>
$"{description.ActionDescriptor.RouteValues["controller"]}_{description.HttpMethod}");
}); });
} }
} }

View File

@ -529,7 +529,7 @@ namespace Jellyfin.Server
var inMemoryDefaultConfig = ConfigurationOptions.DefaultConfiguration; var inMemoryDefaultConfig = ConfigurationOptions.DefaultConfiguration;
if (startupConfig != null && !startupConfig.HostWebClient()) if (startupConfig != null && !startupConfig.HostWebClient())
{ {
inMemoryDefaultConfig[HttpListenerHost.DefaultRedirectKey] = "swagger/index.html"; inMemoryDefaultConfig[HttpListenerHost.DefaultRedirectKey] = "api-docs/swagger";
} }
return config return config

View File

@ -69,7 +69,7 @@ namespace Jellyfin.Server
app.Use(serverApplicationHost.ExecuteWebsocketHandlerAsync); app.Use(serverApplicationHost.ExecuteWebsocketHandlerAsync);
// TODO use when old API is removed: app.UseAuthentication(); // TODO use when old API is removed: app.UseAuthentication();
app.UseJellyfinApiSwagger(); app.UseJellyfinApiSwagger(_serverConfigurationManager);
app.UseRouting(); app.UseRouting();
app.UseAuthorization(); app.UseAuthorization();
app.UseEndpoints(endpoints => app.UseEndpoints(endpoints =>