domaindrivendev / Swashbuckle.AspNetCore

Swagger tools for documenting API's built on ASP.NET Core
MIT License
5.22k stars 1.31k forks source link

Allow CORS on swagger.json endpoint only #2078

Open cyrildurand opened 3 years ago

cyrildurand commented 3 years ago

I can't find a way to enable CORS on the swagger.json endpoint only whithout applying CORS for whole API.

I read the documentation here : https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1#enable-cors-with-attributes and I understand how I can enable cors for the whole API including the swagger.json endpoint but my external application only need to access my swagger.json definition.

It would be a nice feature if we can specify the CORS policy for the swagger.json endpoint :

something like

 app.UseSwagger(c => {
     c.EnableCors("MyCorsPolicy"); 
 });

or maybe

 app.UseSwagger(c => {
     c.AddMetadataEndpoint(new EnableCorsAttribute("MyCorsPolicy")) 
 });

This question has also been posted on stackoverflow here : https://stackoverflow.com/questions/60232282/add-cors-policy-for-swagger-endpoints-only

wu-yafeng commented 3 years ago

I create a pr for this.

before merged, the solution is creating a extensions method.


public static IEndpointConventionBuilder MapSwagger(
            this IEndpointRouteBuilder endpoints,
            string pattern = "/swagger/{documentName}/swagger.json",
            Action<SwaggerEndpointOptions> setupAction = null)
        {
            if (!RoutePatternFactory.Parse(pattern).Parameters.Any(x => x.Name == "documentName"))
            {
                throw new ArgumentException("Pattern must contain '{documentName}' parameter", nameof(pattern));
            }

            Action<SwaggerOptions> endpointSetupAction = options =>
            {
                var endpointOptions = new SwaggerEndpointOptions();

                setupAction?.Invoke(endpointOptions);

                options.RouteTemplate = pattern;
                options.SerializeAsV2 = endpointOptions.SerializeAsV2;
                options.PreSerializeFilters.AddRange(endpointOptions.PreSerializeFilters);
            };

            var pipeline = endpoints.CreateApplicationBuilder()
                .UseSwagger(endpointSetupAction)
                .Build();

            return endpoints.MapGet(pattern, pipeline);
        }

Update your Startup.cs

app.UseEnpoint(endpoint=>{
    endpoint.MapSwagger().RequireCors();
});
cyrildurand commented 3 years ago

Thanks for your reply and pull request.

I finally took time to test your extension method and everything work.

sanme98 commented 1 year ago

Hi, can you share your sample code? I can't make it work. Thanks.