swagger path $ref for OPTIONS requests - swagger

I want to construct an API gateway deployment from a swagger.yml file. I need to support CORS for all endpoints. All my options path definitions are exactly the same. How do I define the options path one place and $ref it where I want to use it?
I was hoping to do something like this (note the $ref: '#/definitions/CorsOptions' at the same level as get):
---
swagger: "2.0"
info:
version: "2016-10-26T03:15:31Z"
title: "corstest"
host: ""
basePath: ""
schemes:
- "https"
paths:
/page:
get:
produces:
- "application/json"
responses:
200:
description: "200 response"
schema:
$ref: "#/definitions/Empty"
headers:
Access-Control-Allow-Origin:
type: "string"
x-amazon-apigateway-integration:
responses:
default:
statusCode: "200"
responseParameters:
method.response.header.Access-Control-Allow-Origin: "'*'"
uri: "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:1234:function:myLambdaFunc/invocations"
passthroughBehavior: "when_no_match"
httpMethod: "GET"
type: "aws_proxy"
$ref: '#/definitions/CorsOptions'
definitions:
Empty:
type: "object"
title: "Empty Schema"
CorsOptions:
options:
consumes:
- "application/json"
produces:
- "application/json"
responses:
200:
description: "200 response"
schema:
$ref: "#/definitions/Empty"
headers:
Access-Control-Allow-Origin:
type: "string"
Access-Control-Allow-Methods:
type: "string"
Access-Control-Allow-Headers:
type: "string"
Cache-Control:
type: "string"
x-amazon-apigateway-integration:
responses:
default:
statusCode: "200"
responseParameters:
method.response.header.Access-Control-Allow-Methods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
method.response.header.Access-Control-Allow-Headers: "'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'"
method.response.header.Access-Control-Allow-Origin: "'*'"
requestTemplates:
application/json: "{\"statusCode\": 200}"
passthroughBehavior: "when_no_match"
type: "mock"
This yaml does not pass swagger validation. How can I pull off what I'm trying to do so my yaml file is not huge and bloated with the same options path definition.
The swagger spec supports $ref as a path item object however I can't figure out where I can put that definition of the path item object. I think API Gateway swagger import restricts pulling yaml files from other places but I'm not 100% sure.

I don't think that will work. API Gateway currently only supports $ref for models and schemas, not for arbitrary objects. We have a backlog item to support $ref in more places, so we might add support for this eventually.

If you would like to specify $ref values in arbitrary places, you can use the expand-swagger-refs module.
This will take a Swagger schema as an input, and automatically inline all your $ref values, giving you back a schema that is suitable for use with API gateway.
It is available on the command line with support for stdin and stdout:
swagger-expand < my-complex-schema.json > aws-compatible.json
And also as an importable Node module:
const { expand, expanded } = require('expand-swagger-refs');
const schema = require('./api/swagger.json');
// Create a copy of the schema, with $ref values expanded:
const expandedSchema = expanded(schema);
// Or expand the schema object in-place (mutates the object):
expand(schema)

Related

Swagger yaml - $ref values must be RFC3986-compliant percent-encoded URIs

I got the following YAML, when I try this, in https://editor.swagger.io/ I'm getting "$ref values must be RFC3986-compliant percent-encoded URIs" error when I use [ and ] brackets, I tried encoding them but the response schema is not getting recognized, saying the reference is missing. Any help on what can be the issue in this scenario?
swagger: "2.0"
info:
title: test
version: "1.0"
paths:
/api/TestCustomer:
post:
consumes:
- application/json
- text/json
produces:
- application/json
- text/json
parameters:
- name: request
in: body
required: true
schema:
$ref: '#/definitions/UpdateTestCustomerRequest'
responses:
'201':
description: Test Response
schema:
$ref: '#/definitions/Result[UpdateTestCustomerResponse]' ***This line results in a error "$ref values must be RFC3986-compliant percent-encoded URIs"
definitions:
UpdateTestCustomerRequest:
type: object
properties:
CustomerId:
type: string
UpdatedBy:
type: string
Result[UpdateTestCustomerResponse]:
type: object
properties:
Status:
format: int32
enum:
- 201
type: integer
Response:
$ref: '#/definitions/UpdateTestCustomerResponse'
UpdateTestCustomerResponse:
type: object
properties:
CustomerId:
type: string
In OpenAPI 2.0, if some schema names contain special characters, they must be URL-encoded in the $ref paths. Replace [ with %5B and ] with %5D in the $ref path, e.g.:
# Incorrect
$ref: '#/definitions/Result[UpdateTestCustomerResponse]'
# Correct
$ref: '#/definitions/Result%5BUpdateTestCustomerResponse%5D'
Or better yet, don't use special characters in schema names.
If/when you migrate to OpenAPI 3, you'll have to remove the [ ] characters from schema names because the newer versions only allow A..Z a..z 0..9 _ . - in schema names.

How do I incorporate JSON schema into my OpenAPI file?

Say I have an OpenAPI swagger.yml file that looks like:
openapi: '3.0.2'
info:
title: Simplest ever
version: '1.0'
servers:
- url: https://api.server.test/v1
paths:
/test:
get:
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
message:
type: string
I prefer to keep the source of truth schema in my schemas/ directory, for example schemas/get.json looks like:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
The intent is for the schemas/*.json to used in my backend code base for validation for incoming and outgoing messages. Goal is to have strong API contracts.
What I don't understand is how to build the swagger.yml file using these JSON schema, instead of duplicating the work in YAML which is really tedious and error prone.
In OpenAPI 3.1, you can reference your JSON Schemas directly:
# openapi: 3.1.0
content:
application/json:
schema:
$ref: 'schemas/get.json'
Earlier OpenAPI versions expect that the JSON Schemas be converted to the OpenAPI Schema Object format (which can be represented as both YAML and JSON). The necessary changes include, for example:
removing unsupported keywords: $schema, patternProperties, and others;
replacing type: [<foo>, 'null'] with type: <foo> + nullable: true;
replacing other type arrays type: [type1, type2, ...] with oneOf/anyOf (OAS3) or removing them (OAS2).
json-schema-to-openapi-schema can automate the conversion.
You can try to $ref vanilla JSON Schemas directly from OAS 2.0 and 3.0 definitions, but some tools will error out on unexpected keywords and constructs.

Does response status code make sense for multiple media types for error status codes as per OpenAPI 3 (Swagger) spec

If we follow the OAS3 spec for Response here we can see that each response status code can have multiple media types and each media type in turn has a schema particular to it.
UseCase : For example oas3 example below, we can see 200 has a binary stream response but 400 has 3 media-types:application/json, application/xml, text/plain.
So is the client expected to request accept-type header with all the media-types mentioned below. How can we have specific media-type for 400 response code, or basically how we can convey to the REST Service to respond with media type as application/xml when its a 400 bad request and if 200 is returning a binary stream.
Does this OAS3 response multiple media-type make sense for Client/Server Errors. If yes then whats the accept-type set for expecting, say "application/xml" for 400 bad request.
Please refer the below swagger UI snap. Where we see a drop-down for the media-types for error code as well. But when we try out executing the rest operations, the accept header is only populated as per the 200 status code's media-type
openapi: 3.0.0
info:
version: "1.0"
title: Resource
description: Resource service
paths:
/resource:
get:
summary: getResource
description: getResource
operationId: get-resource
responses:
"200":
description: a binary document to be returned
content:
application/octet-stream:
schema:
type: string
format: binary
"400":
description: Bad Request
content:
application/json:
schema:
$ref: "#/components/schemas/Error400Element"
application/xml:
schema:
$ref: "#/components/schemas/Error400Element"
text/plain:
schema:
$ref: "#/components/schemas/Error400Element"
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: "#/components/schemas/Error500Element"
application/xml:
schema:
$ref: "#/components/schemas/Error500Element"
text/plain:
schema:
$ref: "#/components/schemas/Error500Element"
servers:
- url: http://localhost:8088/
components:
schemas:
Error400Element:
type: object
required:
- name
properties:
name:
type: string
number:
type: integer
Error500Element:
type: object
properties:
number:
type: integer
flag:
type: boolean
EDIT : modified the OAS3 spec and the SwaggerUI

Swagger/open api 3.0 links not rendered properly [duplicate]

I'm writing an Open API 3.0 spec and trying to get response links to render in Swagger UI v 3.18.3.
Example:
openapi: 3.0.0
info:
title: Test
version: '1.0'
tags:
- name: Artifacts
paths:
/artifacts:
post:
tags:
- Artifacts
operationId: createArtifact
requestBody:
content:
application/octet-stream:
schema:
type: string
format: binary
responses:
201:
description: create
headers:
Location:
schema:
type: string
format: uri
example: /artifacts/100
content:
application/json:
schema:
type: object
properties:
artifactId:
type: integer
format: int64
links:
Read Artifact:
operationId: getArtifact
parameters:
artifact-id: '$response.body#/artifactId'
/artifacts/{artifact-id}:
parameters:
- name: artifact-id
in: path
required: true
schema:
type: integer
format: int64
get:
tags:
- Artifacts
operationId: getArtifact
responses:
200:
description: read
content:
application/octet-stream:
schema:
type: string
format: binary
renders a link like this:
Is this expected? I ask because the operationId is exposed on the UI and parameters is shown as a JSON reference make it seem like something is not displaying properly. I would have expected a hyperlink or something to take me to the appropriate section in the Swagger web page that corresponds to the API being referenced by the link.
Yes this is how Swagger UI currently renders OAS3 links. Rendering of links is one of the things on their OAS3 support backlog:
OAS 3.0 Support Backlog
This is a collection ticket for OAS3 specification features that are not yet supported by Swagger-UI.
...
[ ] Links can't be used to stage another operation
[ ] Link-level servers are not available for executing requests

How to define global parameters in OpenAPI?

I'm preparing my API documentation by doing it per hand and not auto generated. There I have headers that should be sent to all APIs and don't know if it is possible to define parameters globally for the whole API or not?
Some of these headers are static and some has to be set when call to API is made, but they are all the same in all APIs, I don't want to copy and paste parameters for each API and each method as this will not be maintainable in the future.
I saw the static headers by API definition but there is no single document for how somebody can set them or use them.
Is this possible at all or not?
It depends on what kind of parameters they are.
The examples below are in YAML (for readability), but you can use http://www.json2yaml.com to convert them to JSON.
Security-related parameters: Authorization header, API keys, etc.
Parameters used for authentication and authorization, such as the Authorization header, API key, pair of API keys, etc. should be defined as security schemes rather than parameters.
In your example, the X-ACCOUNT looks like an API key, so you can use:
swagger: "2.0"
...
securityDefinitions:
accountId:
type: apiKey
in: header
name: X-ACCOUNT
description: All requests must include the `X-ACCOUNT` header containing your account ID.
# Apply the "X-ACCOUNT" header globally to all paths and operations
security:
- accountId: []
or in OpenAPI 3.0:
openapi: 3.0.0
...
components:
securitySchemes:
accountId:
type: apiKey
in: header
name: X-ACCOUNT
description: All requests must include the `X-ACCOUNT` header containing your account ID.
# Apply the "X-ACCOUNT" header globally to all paths and operations
security:
- accountId: []
Tools may handle security schemes parameters differently than generic parameters. For example, Swagger UI won't list API keys among operation parameters; instead, it will display the "Authorize" button where your users can enter their API key.
Generic parameters: offset, limit, resource IDs, etc.
OpenAPI 2.0 and 3.0 do not have a concept of global parameters. There are existing feature requests:
Allow for responses and parameters shared across all endpoints
Group multiple parameter definitions for better maintainability
The most you can do is define these parameters in the global parameters section (in OpenAPI 2.0) or the components/parameters section (in OpenAPI 3.0) and then $ref all parameters explicitly in each operation. The drawback is that you need to duplicate the $refs in each operation.
swagger: "2.0"
...
paths:
/users:
get:
parameters:
- $ref: '#/parameters/offset'
- $ref: '#/parameters/limit'
...
/organizations:
get:
parameters:
- $ref: '#/parameters/offset'
- $ref: '#/parameters/limit'
...
parameters:
offset:
in: query
name: offset
type: integer
minimum: 0
limit:
in: query
name: limit
type: integer
minimum: 1
maximum: 50
To reduce code duplication somewhat, parameters that apply to all operations on a path can be defined on the path level rather than inside operations.
paths:
/foo:
# These parameters apply to both GET and POST
parameters:
- $ref: '#/parameters/some_param'
- $ref: '#/parameters/another_param'
get:
...
post:
...
If you're talking about header parameters sent by consumer when calling the API...
You can at least define them once and for all in parameters sections then only reference them when needed.
In the example below:
CommonPathParameterHeader, ReusableParameterHeader and AnotherReusableParameterHeader are defined once and for all in parameterson the root of the document and can be used in any parameters list
CommonPathParameterHeaderis referenced in parameters section of /resources and /other-resources paths, meaning that ALL operation of these paths need this header
ReusableParameterHeader is referenced in get /resources meaning that it's needed on this operation
Same thing for AnotherReusableParameterHeader in get /other-resources
Example:
swagger: '2.0'
info:
version: 1.0.0
title: Header API
description: A simple API to learn how you can define headers
parameters:
CommonPathParameterHeader:
name: COMMON-PARAMETER-HEADER
type: string
in: header
required: true
ReusableParameterHeader:
name: REUSABLE-PARAMETER-HEADER
type: string
in: header
required: true
AnotherReusableParameterHeader:
name: ANOTHER-REUSABLE-PARAMETER-HEADER
type: string
in: header
required: true
paths:
/resources:
parameters:
- $ref: '#/parameters/CommonPathParameterHeader'
get:
parameters:
- $ref: '#/parameters/ReusableParameterHeader'
responses:
'200':
description: gets some resources
/other-resources:
parameters:
- $ref: '#/parameters/CommonPathParameterHeader'
get:
parameters:
- $ref: '#/parameters/AnotherReusableParameterHeader'
responses:
'200':
description: gets some other resources
post:
responses:
'204':
description: Succesfully created.
If you're talking about header sent with each API response...
Unfortunately you cannot define reusable response headers.
But at least you can define a reusable response containing these headers for common HTTP responses such as a 500 error.
Example:
swagger: '2.0'
info:
version: 1.0.0
title: Header API
description: A simple API to learn how you can define headers
parameters:
CommonPathParameterHeader:
name: COMMON-PARAMETER-HEADER
type: string
in: header
required: true
ReusableParameterHeader:
name: REUSABLE-PARAMETER-HEADER
type: string
in: header
required: true
AnotherReusableParameterHeader:
name: ANOTHER-REUSABLE-PARAMETER-HEADER
type: string
in: header
required: true
paths:
/resources:
parameters:
- $ref: '#/parameters/CommonPathParameterHeader'
get:
parameters:
- $ref: '#/parameters/ReusableParameterHeader'
responses:
'200':
description: gets some resources
headers:
X-Rate-Limit-Remaining:
type: integer
X-Rate-Limit-Reset:
type: string
format: date-time
/other-resources:
parameters:
- $ref: '#/parameters/CommonPathParameterHeader'
get:
parameters:
- $ref: '#/parameters/AnotherReusableParameterHeader'
responses:
'200':
description: gets some other resources
headers:
X-Rate-Limit-Remaining:
type: integer
X-Rate-Limit-Reset:
type: string
format: date-time
post:
responses:
'204':
description: Succesfully created.
headers:
X-Rate-Limit-Remaining:
type: integer
X-Rate-Limit-Reset:
type: string
format: date-time
'500':
$ref: '#/responses/Standard500ErrorResponse'
responses:
Standard500ErrorResponse:
description: An unexpected error occured.
headers:
X-Rate-Limit-Remaining:
type: integer
X-Rate-Limit-Reset:
type: string
format: date-time
About OpenAPI (fka. Swagger) Next version
The OpenAPI spec (fka. Swagger) will evolve and include the definition of reusable response headers among other things (cf. https://github.com/OAI/OpenAPI-Specification/issues/563).
As per this Swagger issue comment, support for global parameters (including header parameters) is not planned in foreseeable future, but to limit the repetition you should use parameters references as in #Arnaud's answer (parameters: - $ref: '#/parameters/paramX').
also wish some global variables, can be used anywhere.
( even in some examples, so can change common settings globally in ui ).
something like
"hello ${var1}" in shell or javascript.
searched docs many times, not found solution yet.
: (

Resources