I'm attempting to implement an API defined in Swagger or OpenAPI 3.0 using AWS API Gateway.
One endpoint in this API takes an abstract base model (lets call it Pet
to be consistent with the well-worn Swagger example), but actually expects a concrete model that is derived from Pet
... Dog
for example.
The concrete model can be determined by a type
attribute on Pet
.
The concrete model can add additional fields.
Of course, this a job for a 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
(taken from here)
However, AWS API Gateway doesn't support discriminator
(ref).
OK, annoying, but maybe a workaround is to define the API with OpenAPI 3.0, and utilise oneOf
in the schema:
paths:
/pets:
patch:
requestBody:
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
However (again), AWS API Gateway doesn't support oneOf
either (ref).
Does anyone know how to implement a model schema of this nature with AWS API Gateway, in particular to take advantage of body validation for an inheritance pattern (Pet <- Dog
)? Or indeed a workaround without having to have methods for every concrete type?
Amazon API Gateway now supports importing Swagger API definitions. Previously, you would use the Swagger importer tool to import Swagger definitions into API Gateway. Now, you can import your Swagger API definitions into API Gateway through the AWS Management Console, CLI, and SDK.
You can connect your API definitions in SwaggerHub to API Gateway by using the Amazon API Gateway integration. The integration will push your API definition to API Gateway every time you save it in SwaggerHub. This way you can quickly create or update an API in API Gateway from SwaggerHub.
This may not be fully satisfactory answer to your question, but there is a way to use oneOf
with API Gateway. You can use JSON schema for individual models according to AWS.
Thanks to that fact you can update your models after API Gateway has been deployed.
# 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}"
This solution works, however might not be greatly sustainable, since you need to execute the patch-operations
after each deployment.
I'll likely update this answer if I find better way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With