Swagger: Adding alternative routes

This commit is contained in:
Zoe Roux 2021-09-19 19:01:48 +02:00
parent 340950177e
commit 4ce462f88f
8 changed files with 94 additions and 23 deletions

View File

@ -3,10 +3,18 @@
<Company>Kyoo</Company> <Company>Kyoo</Company>
<Authors>Kyoo</Authors> <Authors>Kyoo</Authors>
<Copyright>Copyright (c) Kyoo</Copyright> <Copyright>Copyright (c) Kyoo</Copyright>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression> <PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
<RequireLicenseAcceptance>true</RequireLicenseAcceptance> <RequireLicenseAcceptance>true</RequireLicenseAcceptance>
<RepositoryUrl>https://github.com/AnonymusRaccoon/Kyoo</RepositoryUrl> <RepositoryUrl>https://github.com/AnonymusRaccoon/Kyoo</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<PackageProjectUrl>https://github.com/AnonymusRaccoon/Kyoo</PackageProjectUrl>
<PackageVersion>1.0.0</PackageVersion>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

View File

@ -1,20 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<Title>Kyoo.Abstractions</Title>
<Authors>Zoe Roux</Authors>
<Description>Base package to create plugins for Kyoo.</Description>
<PackageProjectUrl>https://github.com/AnonymusRaccoon/Kyoo</PackageProjectUrl>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<RepositoryUrl>https://github.com/AnonymusRaccoon/Kyoo</RepositoryUrl>
<Company>SDG</Company>
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageVersion>1.0.0</PackageVersion>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<LangVersion>default</LangVersion> <LangVersion>default</LangVersion>
<Title>Kyoo.Abstractions</Title>
<Description>Base package to create plugins for Kyoo.</Description>
<RootNamespace>Kyoo.Abstractions</RootNamespace> <RootNamespace>Kyoo.Abstractions</RootNamespace>
</PropertyGroup> </PropertyGroup>
@ -22,9 +11,9 @@
<PackageReference Include="Autofac" Version="6.2.0" /> <PackageReference Include="Autofac" Version="6.2.0" />
<PackageReference Include="JetBrains.Annotations" Version="2021.2.0" /> <PackageReference Include="JetBrains.Annotations" Version="2021.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" />
<PackageReference Include="System.ComponentModel.Composition" Version="5.0.0" /> <PackageReference Include="System.ComponentModel.Composition" Version="5.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,19 @@
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc;
namespace Kyoo.Abstractions.Models.Attributes
{
/// <summary>
/// A custom <see cref="HttpGetAttribute"/> that indicate an alternatives, hidden route.
/// </summary>
public class AltHttpGetAttribute : HttpGetAttribute
{
/// <summary>
/// Create a new <see cref="AltHttpGetAttribute"/>.
/// </summary>
/// <param name="template">The route template, see <see cref="RouteAttribute.Template"/>.</param>
public AltHttpGetAttribute([NotNull] [RouteTemplateAttribute] string template)
: base(template)
{ }
}
}

View File

@ -0,0 +1,39 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc;
namespace Kyoo.Abstractions.Models.Attributes
{
/// <summary>
/// A custom <see cref="RouteAttribute"/> that indicate an alternatives, hidden route.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class AltRouteAttribute : RouteAttribute
{
/// <summary>
/// Create a new <see cref="AltRouteAttribute"/>.
/// </summary>
/// <param name="template">The route template, see <see cref="RouteAttribute.Template"/>.</param>
public AltRouteAttribute([NotNull] [RouteTemplateAttribute] string template)
: base(template)
{ }
}
}

View File

@ -60,6 +60,7 @@
<ItemGroup> <ItemGroup>
<Content Include="../../LICENSE" CopyToOutputDirectory="Always" Visible="false" /> <Content Include="../../LICENSE" CopyToOutputDirectory="Always" Visible="false" />
<Content Include="../../AUTHORS.md" CopyToOutputDirectory="Always" Visible="false" />
<Content Include="settings.json" CopyToOutputDirectory="PreserveNewest" /> <Content Include="settings.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -22,6 +22,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Core.Models.Options; using Kyoo.Core.Models.Options;
@ -30,8 +31,8 @@ using Microsoft.Extensions.Options;
namespace Kyoo.Core.Api namespace Kyoo.Core.Api
{ {
[Route("api/collection")]
[Route("api/collections")] [Route("api/collections")]
[AltRoute("api/collection")]
[ApiController] [ApiController]
[PartialPermission(nameof(CollectionApi))] [PartialPermission(nameof(CollectionApi))]
public class CollectionApi : CrudApi<Collection> public class CollectionApi : CrudApi<Collection>
@ -51,8 +52,8 @@ namespace Kyoo.Core.Api
_thumbs = thumbs; _thumbs = thumbs;
} }
[HttpGet("{id:int}/show")]
[HttpGet("{id:int}/shows")] [HttpGet("{id:int}/shows")]
[AltHttpGet("{id:int}/show")]
[PartialPermission(Kind.Read)] [PartialPermission(Kind.Read)]
public async Task<ActionResult<Page<Show>>> GetShows(int id, public async Task<ActionResult<Page<Show>>> GetShows(int id,
[FromQuery] string sortBy, [FromQuery] string sortBy,
@ -77,8 +78,8 @@ namespace Kyoo.Core.Api
} }
} }
[HttpGet("{slug}/show")]
[HttpGet("{slug}/shows")] [HttpGet("{slug}/shows")]
[AltHttpGet("{slug}/show")]
[PartialPermission(Kind.Read)] [PartialPermission(Kind.Read)]
public async Task<ActionResult<Page<Show>>> GetShows(string slug, public async Task<ActionResult<Page<Show>>> GetShows(string slug,
[FromQuery] string sortBy, [FromQuery] string sortBy,
@ -103,8 +104,8 @@ namespace Kyoo.Core.Api
} }
} }
[HttpGet("{id:int}/library")]
[HttpGet("{id:int}/libraries")] [HttpGet("{id:int}/libraries")]
[AltHttpGet("{id:int}/library")]
[PartialPermission(Kind.Read)] [PartialPermission(Kind.Read)]
public async Task<ActionResult<Page<Library>>> GetLibraries(int id, public async Task<ActionResult<Page<Library>>> GetLibraries(int id,
[FromQuery] string sortBy, [FromQuery] string sortBy,
@ -129,8 +130,8 @@ namespace Kyoo.Core.Api
} }
} }
[HttpGet("{slug}/library")]
[HttpGet("{slug}/libraries")] [HttpGet("{slug}/libraries")]
[AltHttpGet("{slug}/library")]
[PartialPermission(Kind.Read)] [PartialPermission(Kind.Read)]
public async Task<ActionResult<Page<Library>>> GetLibraries(string slug, public async Task<ActionResult<Page<Library>>> GetLibraries(string slug,
[FromQuery] string sortBy, [FromQuery] string sortBy,

View File

@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.1" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.1" />
<PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="6.2.1" />
<ProjectReference Include="../Kyoo.Abstractions/Kyoo.Abstractions.csproj" /> <ProjectReference Include="../Kyoo.Abstractions/Kyoo.Abstractions.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -19,9 +19,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models.Attributes;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
@ -47,9 +48,9 @@ namespace Kyoo.Swagger
/// <inheritdoc /> /// <inheritdoc />
public void Configure(IServiceCollection services) public void Configure(IServiceCollection services)
{ {
services.AddSwaggerGen(x => services.AddSwaggerGen(options =>
{ {
x.SwaggerDoc("v1", new OpenApiInfo options.SwaggerDoc("v1", new OpenApiInfo
{ {
Version = "v1", Version = "v1",
Title = "Kyoo API", Title = "Kyoo API",
@ -67,7 +68,15 @@ namespace Kyoo.Swagger
}); });
foreach (string documentation in Directory.GetFiles(AppContext.BaseDirectory, "*.xml")) foreach (string documentation in Directory.GetFiles(AppContext.BaseDirectory, "*.xml"))
x.IncludeXmlComments(documentation); options.IncludeXmlComments(documentation);
options.UseAllOfForInheritance();
options.DocInclusionPredicate((_, apiDescription) =>
{
return apiDescription.ActionDescriptor.EndpointMetadata
.All(x => x is not AltRouteAttribute && x is not AltHttpGetAttribute);
});
}); });
} }
@ -78,6 +87,10 @@ namespace Kyoo.Swagger
SA.New<IApplicationBuilder>(app => app.UseSwaggerUI(x => SA.New<IApplicationBuilder>(app => app.UseSwaggerUI(x =>
{ {
x.SwaggerEndpoint("/swagger/v1/swagger.json", "Kyoo v1"); x.SwaggerEndpoint("/swagger/v1/swagger.json", "Kyoo v1");
}), SA.Before),
SA.New<IApplicationBuilder>(app => app.UseReDoc(x =>
{
x.SpecUrl = "/swagger/v1/swagger.json";
}), SA.Before) }), SA.Before)
}; };
} }