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

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.

Related

swagger codegen missing attributes with allOf

We are using the latest swagger-codegen-cli (currently v2.4.28) to generate a python client from a swagger yaml file. We use allOf throughout our specification to re-use definitions across multiple types of response objects. When generating a python client we notice that model classes generated seem to be missing any attributes defined in the first allOf reference.
The specification is valid, and there are no errors or warnings generated that would indicate a problem so I am not sure if this is a bug or if we've misunderstood the intended usage.
Here is a minimal example that illustrates the problem.
swagger: '2.0'
info:
version: "0.1.0"
title: Sample
host: localhost:8080
schemes:
- https
basePath: /sample/v1
paths:
/info:
get:
summary: Get Info
operationId: getInfo
produces:
- application/json
tags:
- Info
responses:
200:
description: Information Response
schema:
$ref: "#/definitions/InfoResponse"
default:
description: Unexpected error
definitions:
InfoResponse:
type: object
allOf:
- $ref: "#/definitions/Part1"
- $ref: "#/definitions/Part2"
- $ref: "#/definitions/Part3"
Part1:
type: object
properties:
a:
type: integer
b:
type: integer
Part2:
type: object
properties:
c:
type: string
d:
type: string
Part3:
type: object
properties:
e:
type: string
f:
type: string
We use the following command to generate the python client.
java -jar swagger-codegen-cli-2.4.28.jar generate -l python -i api-specification.yaml -o codegen
The python model class for the InfoResponse object has the following swagger_types and attribute_map values.
swagger_types = {
'c': 'str',
'd': 'str',
'e': 'str',
'f': 'str'
}
attribute_map = {
'c': 'c',
'd': 'd',
'e': 'e',
'f': 'f'
}
As you can see, the two attributes from the Part1 reference are missing (i.e., "a", and "b"). If I reorder the references so that Part2 is first then "c" and "d" go missing and "a" and "b" are present. Like this:
InfoResponse:
type: object
allOf:
- $ref: "#/definitions/Part2"
- $ref: "#/definitions/Part1"
- $ref: "#/definitions/Part3"
It would appear as though the first reference in the list is always ignored. Is this a bug, a template problem, are the definitions not specified correctly, or am I not understanding how this is supposed to work?

Swagger 2.0 duplicated mapping key parser error

I have a swagger file for an API that is going to reside inside IBM API Connect. I typed it out from an IBM tutorial, and I was trying to replicate what the instructor was doing(he did not provide any source files, so I had to type it out).
The tutorial is available here: https://www.youtube.com/watch?v=hCvUYd67rbI
The guy is copy-pasting the swagger file inside the APIConnect local designer around 21:40.
I took the swagger file and put it into http://editor.swagger.io/ and I got a bunch of parser errors:
Errors
Hide
Parser error duplicated mapping key
Jump to line 31
Semantic error at definitions.shipping.properties.xyz.type
Sibling values are not allowed alongside $refs
Jump to line 86
Semantic error at definitions.shipping.properties.cek.type
Sibling values are not allowed alongside $refs
Jump to line 89
I did some digging, and I did not find a lot of resources for my kind of problem. I double-checked if I typed it out correctly from the tutorial. Maybe it has something to do with an older version of API Connect being used in ths tutorial.
Thanks in advance for anyone who can help.
EDIT:
Sorry, it was a bit late so I was tired, I am adding the source code in the yaml file:
info:
x-ibm-name: logistics
title: logistics
version: 1.0.0
schemes:
- https
basePath: /logistics
consumes:
- application/json
produces:
- application/json
securityDefinitions:
clientIdHeader:
type: apiKey
in: header
name: X-IBM-Client-Id
security:
- clientdHeader: []
x-ibm-configuration:
testable: true
enforced: true
cors:
enabled: true
gateway: datapower-gateway
catalogs:
apic-dev:
properties:
runtime-url: $(TARGET_URL)
properties:
shipping_svc_url:
value: 'http://shipping.think.ibm:5000/calculate'
description: Location of the shipping calculator service
encoded: false
paths:
/shipping:
get:
responses:
'200':
description: 200 OK
schema:
$ref: '#/definitions/shipping'
summary: Calculate shipping costs to a destination zip code
operationId: shipping.calc
parameters:
- name: zip
type: string
required: true
in: query
description: Destination zip code.
/stores:
get:
responses:
'200':
description: 200 OK
schema:
$ref: '#/definitions/store_location'
tags:
- stores
summary: Locate store near zip code
operationId: get.stores
parameters:
- name: zip
type: string
required: true
in: query
definitions:
rates:
properties:
next_day:
type: string
example: '20.00'
two_day:
type: string
example: '17.00'
ground:
type: string
example: '8.00'
required:
- two_day
- next_day
- ground
shipping:
properties:
xyz:
type: string
$ref: '#/definitions/rates'
cek:
type: string
$ref: '#/definitions/rates'
required:
- xyz
- cek
store_location:
properties:
google_maps_link:
type: string
example: 'https://www.google.com/maps?q=34.1030032,-118.4104684'
required:
- google_maps_link
There's typo: securityDefinitions defines clientIdHeader, but security refers to clientdHeader (..ntd.. instead of ..enId..).
"Sibling values are not allowed alongside $refs" is not a syntax error, but rather a warning. It's caused by this line:
definitions:
rates:
properties:
...
shipping:
properties:
xyz:
type: string # <---------------
$ref: '#/definitions/rates'
$ref is a JSON Reference, it works by replacing itself and all sibling attributes with the content the $ref is pointing at. So, the type attribute and any other attributes alongside $ref will be ignored. The warning informs you about this in case there are important attributes alongside $ref -- these attributes need to be moved into the $ref'erenced schema to have effect.
That said, xyz being type: string does not make sense, because rates is an object and not a string.
You should also consider adding type: object to the rates, shipping and store_location definitions to indicate that they are objects.

Swagger parameter error "is not exactly one from <#/definitions/parameter>"?

I'm trying to write a simple Swagger / Open API definition using the Swagger Editor.
swagger: "2.0"
info:
version: 1.0.0
title: Test API
description: Test API
schemes:
- https
host: hipaa.ai
basePath: /v1
paths:
/comments:
post:
summary: Your comments
description: Comments
parameters:
- name: text
in: body
description: An array of text strings
type: array
minItems: 1
maxItems: 1000
items:
type: text
I'm getting the following error:
Schema error at paths./comments.post.parameters[0]
is not exactly one from <#/definitions/parameter>,<#/definitions/jsonReference>
I've checked the Swagger schema reference, and the petstore example, but I'm not sure why I'm getting this. Any ideas?
Body parameters use the schema keyword to specify the type, so you need to move type, items, minItems and maxItems under schema.
Also, type: text is not a valid type. Use type: string instead.
parameters:
- name: text
in: body
description: An array of text strings
schema:
type: array
minItems: 1
maxItems: 1000
items:
type: string

swagger path $ref for OPTIONS requests

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)

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