Skip to content

Commit

Permalink
Handle multiple document versions by using options snapshot as a base…
Browse files Browse the repository at this point in the history
… to create a separate endpoint
  • Loading branch information
Sukharev Andrey committed Feb 15, 2021
1 parent 2e80937 commit 46d829d
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 7 deletions.
9 changes: 6 additions & 3 deletions src/Swashbuckle.AspNetCore.ReDoc/ReDocBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ public static IApplicationBuilder UseReDoc(this IApplicationBuilder app, ReDocOp
this IApplicationBuilder app,
Action<ReDocOptions> setupAction = null)
{
var options = app.ApplicationServices.GetRequiredService<IOptions<ReDocOptions>>().Value;

setupAction?.Invoke(options);
ReDocOptions options;
using (var scope = app.ApplicationServices.CreateScope())
{
options = scope.ServiceProvider.GetRequiredService<IOptionsSnapshot<ReDocOptions>>().Value;
setupAction?.Invoke(options);
}

// To simplify the common case, use a default that will work with the SwaggerMiddleware defaults
if (options.SpecUrl == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ public static IApplicationBuilder UseSwaggerUI(this IApplicationBuilder app, Swa
this IApplicationBuilder app,
Action<SwaggerUIOptions> setupAction = null)
{
var options = app.ApplicationServices.GetRequiredService<IOptions<SwaggerUIOptions>>().Value;

setupAction?.Invoke(options);
SwaggerUIOptions options;
using (var scope = app.ApplicationServices.CreateScope())
{
options = scope.ServiceProvider.GetRequiredService<IOptionsSnapshot<SwaggerUIOptions>>().Value;
setupAction?.Invoke(options);
}

// To simplify the common case, use a default that will work with the SwaggerMiddleware defaults
if (options.ConfigObject.Urls == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,19 @@ public async Task IndexUrl_IgnoresUrlCase()
Assert.Contains("Redoc.init", indexContent);
Assert.Equal(HttpStatusCode.OK, jsResponse.StatusCode);
}

[Theory]
[InlineData("/redoc/1.0/index.html", "/swagger/1.0/swagger.json")]
[InlineData("/redoc/2.0/index.html", "/swagger/2.0/swagger.json")]
public async Task VersionUrls_ProperlyHandlesDifferentVersions(string redocUrl, string swaggerPath)
{
var client = new TestSite(typeof(MultipleVersions.Startup)).BuildClient();

var response = await client.GetAsync(redocUrl);
var content = await response.Content.ReadAsStringAsync();

Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Contains(swaggerPath, content);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,23 @@ public async Task IndexUrl_ReturnsCustomIndexHtml_IfConfigured()

Assert.Contains("Example.com", content);
}

[Theory]
[InlineData("/swagger/index.html", new [] { "Version 1.0", "Version 2.0" })]
[InlineData("/swagger/1.0/index.html", new [] { "Version 1.0" })]
[InlineData("/swagger/2.0/index.html", new [] { "Version 2.0" })]
public async Task VersionUrls_ProperlyHandlesDifferentVersions(string swaggerUiUrl, string[] versions)
{
var client = new TestSite(typeof(MultipleVersions.Startup)).BuildClient();

var response = await client.GetAsync(swaggerUiUrl);
var content = await response.Content.ReadAsStringAsync();

Assert.Equal(HttpStatusCode.OK, response.StatusCode);
foreach (var version in versions)
{
Assert.Contains(version, content);
}
}
}
}
1 change: 1 addition & 0 deletions test/WebSites/MultipleVersions/MultipleVersions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\Swashbuckle.AspNetCore.ReDoc\Swashbuckle.AspNetCore.ReDoc.csproj" />
<ProjectReference Include="..\..\..\src\Swashbuckle.AspNetCore.Swagger\Swashbuckle.AspNetCore.Swagger.csproj" />
<ProjectReference Include="..\..\..\src\Swashbuckle.AspNetCore.SwaggerGen\Swashbuckle.AspNetCore.SwaggerGen.csproj" />
<ProjectReference Include="..\..\..\src\Swashbuckle.AspNetCore.SwaggerUI\Swashbuckle.AspNetCore.SwaggerUI.csproj" />
Expand Down
22 changes: 21 additions & 1 deletion test/WebSites/MultipleVersions/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVers
app.UseDeveloperExceptionPage();
}

app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();
Expand All @@ -48,13 +50,31 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVers
});

app.UseSwagger();

// A common endpoint that contains both versions
app.UseSwaggerUI(c =>
{
c.RoutePrefix = "swagger";
foreach (var description in provider.ApiVersionDescriptions)
{
c.SwaggerEndpoint($"{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", $"Version {description.GroupName}");
}
});

// Separate endpoints that contain only one version
foreach (var description in provider.ApiVersionDescriptions)
{
app.UseSwaggerUI(c =>
{
c.RoutePrefix = $"swagger/{description.GroupName}";
c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", $"Version {description.GroupName}");
});
app.UseReDoc(c =>
{
c.RoutePrefix = $"redoc/{description.GroupName}";
c.SpecUrl($"/swagger/{description.GroupName}/swagger.json");
});
}
}
}
}

0 comments on commit 46d829d

Please sign in to comment.