【问题标题】:How to generate Options(CORS) with Swagger如何使用 Swagger 生成选项(CORS)
【发布时间】:2017-07-24 13:00:03
【问题描述】:

对于我们正在进行的项目,我们会自动生成一个 Swagger 文件。然而,此时我们正在努力解决 CORS 部分。

我们正在使用 Amazon API 网关导入 api 功能。要将其与 Swagger 和 CORS 结合使用,我们必须在源代码中创建一个额外的操作(操作),它允许每个 api 方法(操作)使用 CORS(选项)! 例如:

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

如您所见,这会使代码变得更脏。这是一个临时修复,但我们找不到其他方法。有没有办法在 swagger 定义文件中自动生成它?或者我们该怎么做,Amazon API 网关需要这个(文档:http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html

【问题讨论】:

  • 你用的是什么版本的swashbuckle?
  • @HelderSepu:我们使用的是 1.0.0 版本 => "Swashbuckle.AspNetCore" Version="1.0.0"

标签: c# asp.net-core swagger aws-api-gateway swashbuckle


【解决方案1】:

您可以通过x-amazon-apigateway-integration swagger 扩展来驱动api网关。

使用 Swashbuckle document filter,您可以在所有路径上生成选项操作,而无需在控制器中执行相应操作。

这是一个示例代码,它将为您的 swagger 中的所有路径生成选项操作,并添加使用 swagger 扩展以在这些 OPTION 方法上生成 api 网关中的模拟:

    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;
            }
        }
    }

不要忘记在 swashbuckle 中注册该过滤器:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
            c.DocumentFilter<AddCorsApiGatewayDocumentFilter>();
        });
    }

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,我最终在 Java 中创建了一个实用程序,它会自动将这些标头添加到 Swagger JSON。您可以在将其导入 API Gateway 之前运行它并导入在所有方法中启用了 CORS 的输出 JSON

    https://github.com/anandlalvb/SwaggerToAPIGateway

    将这些标头添加到 Swagger JSON 中的所有方法中是一项繁琐的任务。

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

    我希望这个实用程序可以帮助您轻松地做到这一点

    【讨论】:

      【解决方案3】:

      但是,结合 Azure API 管理,我遇到了完全相同的问题。我使用了 asidis 的代码并对其进行了修改以满足我的需要。

      显然,我删除了 AWS 扩展部分并使用了更新版本的 Swashbuckle.AspNetCore 包 (5.5.1)

      public class CorsDocumentFilter : IDocumentFilter
      {
          private const string AcaOrigin = "Access-Control-Allow-Origin";
          private const string AcaMethods = "Access-Control-Allow-Methods";
          private const string AcaHeaders = "Access-Control-Allow-Headers";
      
          private static OpenApiOperation BuildCorsOptionOperation(OpenApiOperation operation)
          {
              var response = new OpenApiResponse
              {
                  Description = "Successful operation",
                  Headers = new Dictionary<string, OpenApiHeader>
                  {
                      { AcaOrigin, new OpenApiHeader {Description = "URI that may access the resource" } },
                      { AcaMethods, new OpenApiHeader {Description = "Method or methods allowed when accessing the resource" } },
                      { AcaHeaders, new OpenApiHeader {Description = "Used in response to a preflight request to indicate which HTTP headers can be used when making the request." } },
                  }
              };
      
              return new OpenApiOperation
              {
                  Summary = "CORS Preflight request",
      
                  // Path parameters are required for Azure APIM
                  Parameters = operation.Parameters.Where(x => x.In == ParameterLocation.Path).ToList(),
                  Tags = new List<OpenApiTag> { new OpenApiTag { Name = "CORS" } },
                  Responses = new OpenApiResponses
                  {
                      { "200", response }
                  },
              };
          }
          
          public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
          {
              foreach (var path in swaggerDoc.Paths)
              {
                  var operation = path.Value.Operations.Values.First();
                  var corsOptionOperation = BuildCorsOptionOperation(operation);
                  path.Value.Operations.Add(OperationType.Options, corsOptionOperation);
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        使用控制台中简单的一键式功能执行“启用 CORS”的步骤,然后部署 API,最后进入舞台并将 API 导出回 swagger。

        现在您可以检查 swagger 以了解如何在您自己的 swagger 中配置 CORS。

        【讨论】:

        • 感谢您的回复,但我想以自动方式创建这些选项。在我们的项目中,我们只是将 swagger 文件交付给 AWS 合作伙伴,然后他们将其导入 API 网关。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-08
        • 2019-11-15
        • 2015-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多