Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate Options(CORS) with Swagger

For a project we are working on we are generating an Swagger File automatically. However at this moment we are struggling with the CORS part.

We are using the Amazon API gateway import api functionality. To use this in combination with Swagger and CORS, we have to create an additional action (operation) in our source code which allows CORS(options) for each api method (operation)! eg:

    [HttpOptions]
    [Route("{id}")]
    [ProducesResponseType((int)HttpStatusCode.OK)]
    public IActionResult UserOptions()
    {
        return new OkResult();
    }

As you can see this makes the code a lot dirtier. this is a temporary fix, but we can not find another way. Is there any way to generate this in the swagger definition file automatically? Or how can we do this, Amazon API gateway required this (documentation: http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html)

like image 738
Rob Van Pamel Avatar asked Jul 24 '17 13:07

Rob Van Pamel


People also ask

How do I enable CORS for Swagger?

The method of enabling CORS depends on the server and/or framework you use to host your application. http://enable-cors.org provides information on how to enable CORS in some common web servers. Other servers/frameworks may provide you information on how to enable it specifically in their use case.

How should we use Swagger to produce static docs?

I usually do it with https://editor.swagger.io/. No installation or anything required. Copy your yml file into the editor and choose 'Generate Client > html2' and it will generate static html files in a zip file.


2 Answers

You can drive api gateway through x-amazon-apigateway-integration swagger extension.

Using Swashbuckle document filter, you can generate a option operation on all your paths without corresponding action in your controller.

Here is a sample code that will generate an option operation for all paths in your swagger and add use swagger extensions to generate a mock in api gateway on these OPTION methods:

    public class AddCorsApiGatewayDocumentFilter : IDocumentFilter
    {
        private Operation BuildCorsOptionOperation()
        {
            var response = new Response
            {
                Description = "Successful operation",
                Headers = new Dictionary<string, Header>
                {
                    { "Access-Control-Allow-Origin", new Header(){Type="string",Description="URI that may access the resource" } },
                    { "Access-Control-Allow-Methods", new Header(){Type="string",Description="Method or methods allowed when accessing the resource" } },
                    { "Access-Control-Allow-Headers", new Header(){Type="string",Description="Used in response to a preflight request to indicate which HTTP headers can be used when making the request." } },
                }
            };
            return new Operation
            {
                Consumes = new List<string> { "application/json" },
                Produces = new List<string> { "application/json" },
                Responses = new Dictionary<string, Response>{{"200",response}}
            };
        }

        private object BuildApiGatewayIntegrationExtension()
        {
            return new
            {
                responses = new
                {
                    @default = new
                    {
                        statusCode = "200",
                        responseParameters = new Dictionary<string, string>
                            {
                                { "method.response.header.Access-Control-Allow-Methods", "'POST,GET,OPTIONS'" },
                                { "method.response.header.Access-Control-Allow-Headers", "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"},
                                { "method.response.header.Access-Control-Allow-Origin", "'*'"}
                            }
                    },
                },
                passthroughBehavior = "when_no_match",
                requestTemplates = new Dictionary<string, string> { { "application/json", "{\"statusCode\": 200}" } },
                type = "mock"
            };
        }

        public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
        {
            foreach (var path in swaggerDoc.Paths)
            {
                var corsOptionOperation = BuildCorsOptionOperation();
                var awsApiGatewayExtension = BuildApiGatewayIntegrationExtension();
                corsOptionOperation.Extensions.Add("x-amazon-apigateway-integration", awsApiGatewayExtension);
                path.Value.Options = corsOptionOperation;
            }
        }
    }

Do not forget to register that filter in swashbuckle:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
            c.DocumentFilter<AddCorsApiGatewayDocumentFilter>();
        });
    }
like image 190
asidis Avatar answered Oct 07 '22 13:10

asidis


I had the same issues and I end up creating a utility in Java which automatically adds these headers to Swagger JSON. You can run it before importing it to API Gateway and import the output JSON which has CORS enabled in all the methods

https://github.com/anandlalvb/SwaggerToAPIGateway

It is tedious task to add these headers to all your methods in Swagger JSON.

            "headers": {
            "Access-Control-Allow-Origin": {
                "type": "string"
            },
            "Access-Control-Allow-Methods": {
                "type": "string"
            },
            "Access-Control-Allow-Headers": {
                "type": "string"
            }
        }

I hope this utility may help you to do that easily

like image 44
binary Avatar answered Oct 07 '22 13:10

binary