【问题标题】:OpenAPI / Swagger model inheritance with AWS API Gateway使用 AWS API Gateway 继承 OpenAPI / Swagger 模型
【发布时间】:2020-03-14 05:06:20
【问题描述】:

我正在尝试使用 AWS API Gateway 实现在 Swagger 或 OpenAPI 3.0 中定义的 API。

此 API 中的一个端点采用抽象基础模型(我们称其为 Pet 以与陈旧的 Swagger 示例保持一致),但实际上需要一个派生自 Pet 的具体模型... @987654326 @例如。

具体模型可以通过Pet 上的type 属性确定。

具体模型可以添加额外的字段。

当然,这是discriminator 的工作:

definitions:
    Pet:
        discriminator: petType
        required:
        - name
        - petType # required for inheritance to work
        properties:
        name: 
            type: string
        petType:
            type: string
    Cat:
        allOf:
        - $ref: '#/definitions/Pet' # Cat has all properties of a Pet
        - properties: # extra properties only for cats
            huntingSkill:
                type: string
                default: lazy
                enum:
                - lazy
                - aggressive
    Dog:
        allOf:
        - $ref: '#/definitions/Pet' # Dog has all properties of a Pet
        - properties: # extra properties only for dogs
            packSize:
                description: The size of the pack the dog is from
                type: integer

(取自here

但是,AWS API Gateway 不支持discriminator (ref)。

好的,烦人,但也许一种解决方法是使用 OpenAPI 3.0 定义 API,并在架构中使用 oneOf

paths:
    /pets:
        patch:
            requestBody:
                content:
                    application/json:
                        schema:
                            oneOf:
                                - $ref: '#/components/schemas/Cat'
                                - $ref: '#/components/schemas/Dog'

但是(再次),AWS API Gateway 也不支持oneOf (ref)。

有谁知道如何使用 AWS API Gateway 实现这种性质的模型架构,特别是利用继承模式的主体验证 (Pet <- Dog)?或者确实是一种解决方法,而不必为每种具体类型提供方法?

【问题讨论】:

  • 有什么解决办法吗?
  • @TolgaEvcimen - 我不知道。我们已经不再使用 AWS API Gateway,因为这种不一致和问题太多了。

标签: amazon-web-services swagger aws-api-gateway openapi


【解决方案1】:

我想添加另一个答案,以更漂亮的方式解决问题!关键问题是在之前的尝试中我使用了 OpenAPI 3.0.0,但是 3.0.1 似乎不再对oneOf 指令有任何问题。

下面是工作示例:

{
  "openapi": "3.0.1",
  "info": {
    // (...)
  },
  "paths": {
    "/pets": {
      "post": {
        "summary": "Post a pet",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PetRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            // (...)
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Cat": {
        "type": "object",
        "required": [
          "cat_stuff"
        ],
        "properties": {
          "cat_stuff": {
            "type": "string"
          }
        }
      },
      "Dog": {
        "type": "object",
        "required": [
          "dog_stuff"
        ],
        "properties": {
          "dog_stuff": {
            "type": "string"
          },
        }
      },
      "PetRequest": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/Cat"
          },
          {
            "$ref": "#/components/schemas/Dog"
          }
        ]
      }
    },
    // Many fields omitted (...)
}

使用与这些模式之一不匹配的有效负载进行卷曲会产生以下错误,这证明 oneOf 正在按预期工作!

(...)
"error_messages": [
    "[instance failed to match exactly one schema (matched 0 out of 2)]"
],

请自行测试并留下一些反馈。

【讨论】:

  • 基本上,解决方案不是在content: application/json: schema: 正下方使用oneOf,而是将响应包装为模型(在components 部分中创建模型),并使用oneOf in你的模型。这样可行!现在 API Gateway 导出的 yaml 将显示正确的 oneOf。
【解决方案2】:

这可能无法完全满足您的问题,但有一种方法可以将oneOf 与 API Gateway 结合使用。 You can use JSON schema for individual models according to AWS.

因此,您可以在部署 API Gateway 后更新模型。

# Reformatted here for readability
VALUE='"{\"$schema\": \"http://json-schema.org/draft-04/schema#\",
         \"title\": \"A Pet Request\",
         \"oneOf\":
        [{ \"$ref\": \"https://apigateway.amazonaws.com/restapis/xxxxxxx/models/Cat\" },
         { \"$ref\": \"https://apigateway.amazonaws.com/restapis/xxxxxxx/models/Dog\" }]}"'


aws apigateway update-model \
--rest-api-id xxxxxxx \
--model-name 'PetRequest' \
--patch-operations "op=replace,path=/schema,value=${VALUE}"

此解决方案有效,但可能不太可持续,因为您需要在每次部署后执行patch-operations

如果我找到更好的方法,我可能会更新这个答案。

【讨论】:

    猜你喜欢
    • 2018-07-29
    • 2020-10-25
    • 2020-06-12
    • 2019-06-09
    • 1970-01-01
    • 2018-02-13
    • 2021-01-11
    • 2021-07-14
    • 1970-01-01
    相关资源
    最近更新 更多