I am building an API documentation, I`m new to programming in general and this is the first time I work in Swagger.
This is my code:
/stareMesaj:
post:
tags:
- Metode disponibile
summary: Stare mesaj
description: Call de verificat stare mesaj. More soon.
operationId: stareMesaj
responses:
'200':
description: Ultimele 60 zile - Nu aveti drept de interogare stare pentru mesaj
headers:
X-Rate-Limit:
description: calls per hour allowed by the user
schema:
type: integer
format: int32
X-Expires-After:
$ref: '#/components/headers/ExpiresAfter'
content:
application/json:
schema:
type: string
examples:
response:
value: Hello world!
application/xml:
schema:
type: string
text/csv:
schema:
type: string
On the responses tag I get the following error:
Structural error at paths./stareMesaj.post.responses
should only have three-digit status codes, `default`, and vendor extensions (`x-*`) as properties
Jump to line 395
I don't know what to do. I googled the error but can't find it. What is the problem here?
Related
I created an API Gateway which uses the x-google-backend to a cloud functions.
When I tried to access it via browser I received a CORS error so I researched and find a solution by adding this to the OpenAPI config where the address part is the same as the cloud function.
options:
operationId: cors
x-google-backend:
address: https://europe-west3-myproject.cloudfunctions.net/api/query
responses:
'200':
description: A successful response
This works! So I removed the public access to the cloud function and gave the gateway service account access to it and tried again.
Which gave me a permission error. After research I found this post explaining the problem and giving me a solution to fix it.
The issue was that I call my define the cloud function with an additional path to call query. I added this to the OpenAPI config:
jwt_audience: https://europe-west3-myproject.cloudfunctions.net/api
So I tried it again in Postman and it works, however in the browser I now get again a CORS error.
So now I am at square one... what should I do?
Here is my complete OpenAPI config:
# openapi2-functions.yaml
swagger: '2.0'
info:
version: 1.0.0
schemes:
- https
produces:
- application/json
paths:
/query:
post:
operationId: api
parameters:
- in: "body"
name: "message"
schema:
$ref: '#/definitions/messasge'
x-google-backend:
address: https://europe-west3-myproject.cloudfunctions.net/api/query
jwt_audience: https://europe-west3-myproject.cloudfunctions.net/api
x-google-quota:
metricCosts:
"read-requests": 1
security:
- api_key: []
responses:
'200':
description: A successful response
schema:
type: string
options:
operationId: cors
x-google-backend:
address: https://europe-west3-myproject.cloudfunctions.net/api/query
responses:
'200':
description: A successful response
securityDefinitions:
# This section configures basic authentication with an API key.
api_key:
type: "apiKey"
name: "key"
in: "query"
x-google-management:
metrics:
# Define a metric for read requests.
- name: "read-requests"
displayName: "Read requests"
valueType: INT64
metricKind: DELTA
quota:
limits:
# Define the limit or the read-requests metric.
- name: "read-limit"
metric: "read-requests"
unit: "1/min/{project}"
values:
STANDARD: 100
definitions:
chatmessage:
type: "object"
properties:
id:
type: string
description: session id
example: "2vr34524tg3"
query:
type: string
description: message
example: "Hello"
required:
- id
- query
According to the documentation Cross-Origin Resource Sharing (CORS) on Cloud Functions has some limitations:
CORS preflight requests are sent without an Authorization header, so they will be rejected on all non-public HTTP Functions. Because the preflight requests fail, the main request will also fail.
To overcome this limitation in your case the mentioned documentation recommends to deploy a Cloud Endpoints proxy and enable CORS. Also you might find useful the Support CORS documentation page for a description of available CORS support options
I need to describe an api having in request body an object with required fields and one of these fields it's an object itself having another set of required fields.
I'm using open api v3 and swagger editor (https://editor.swagger.io/)
After i put my .yaml file onto the editor I generate an html client (> generate client > html). Then I open the static page index.html generated in the .zip file obtaning this schema:
Table of Contents
body
secureoauthservicesv2Nested_nestedobj
body
id
Integer id of nested obj
nestedobj
secureoauthservicesv2Nested_nestedobj
secureoauthservicesv2Nested_nestedobj
nested object
field1 (optional)
String
field2 (optional)
String
I expect field1 to be required and field2 to be optional but it's not.
This is my .yaml file
openapi: 3.0.0
info:
title: Example API
description: Example API specification
version: 0.0.1
servers:
- url: https://example/api
paths:
/secure/oauth/services/v2/Nested:
post:
summary: Try nested
description: Used to post Nested obj
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- id
- nestedobj
properties:
id:
type: integer
description: id of nested obj
nestedobj:
type: object
required:
- field1
description: nested object
properties:
field1:
type: string
field2:
type: string
responses:
'200':
description: Nested object OK
Solved!
I used components and schemas, but I think this could be a bug, opened an issue on swagger editor repo:
https://github.com/swagger-api/swagger-editor/issues/1952
openapi: 3.0.0
info:
title: Example API
description: Example API specification
version: 0.0.2
servers:
- url: https://example/api
paths:
/secure/oauth/services/v2/Nested:
post:
summary: Try nested
description: Used to post Nested obj
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- id
- nestedobj
properties:
id:
type: integer
description: id of nested obj
nestedobj:
$ref: '#/components/schemas/nestedobj'
responses:
'200':
description: Nested object OK
components:
schemas:
element:
type: object
required:
- fieldArray1
properties:
fieldArray1:
type: string
description: field array
fieldArray2:
type: number
nestedobj:
type: object
required:
- field1
description: nested object
properties:
field1:
$ref: '#/components/schemas/woah'
field2:
type: string
woah:
type: object
required:
- woahthis
description: woah this
properties:
field3:
type: array
items:
$ref: '#/components/schemas/element'
woahthis:
type: number
description: numeber woah this
EDIT 23/08/21:
I opened a bug in swagger-codegen github in april 2019 but it still has no response whatsoever
Is it possible to use templating w/ swagger.
How is it done.
I do not want to repeat the three properties time, len and off each time.
Have a look at the end of this post where I made up a 'template' for explanation.
More Detail:
I have a JSON response structure which always returns a JSON always with the same properties but only the content of data is subject to change.
data could be an array, could be a string, a number, null or an object.
That depends on the Api's function handling.
{
time: "2019-02-01T12:12:324",
off: 13,
len: 14,
data: [
"Last item in the row of 14 items :-)"
]
}
See at the end of this post for my example of the Swagger definition.
It is a yaml which can be pasted into the swagger editor at https://editor.swagger.io/
In the swagger documentation (yaml) I do not want to repeat the statically reoccuring items, which will not change in their functionality for any other request.
Let me know, if the question is not precisely enough to understand.
swagger: "2.0"
info:
description: ""
version: 1.0.0
title: "Templating?"
contact:
email: "someone#somewhere.com"
host: localhost
basePath: /api
paths:
/items:
get:
summary: "list of items"
produces:
- application/json
responses:
200:
description: "successful operation"
schema:
$ref: "#/definitions/Items"
/item/{id}:
get:
summary: "specific item"
produces:
- application/json
parameters:
- name: id
in: path
description: "ID of the demanded item"
required: true
responses:
200:
description: "successful operation"
schema:
$ref: "#/definitions/Item"
definitions:
Items:
type: object
description: ""
properties:
time:
type: string
format: date-time
description: "date-time of the request"
off:
type: integer
description: "index 0 based offset of list data"
default: 0
len:
type: integer
description: "overall amount of items returned"
default: -1
data:
type: array
items:
$ref: "#/definitions/ListingItem"
Item:
type: object
description: ""
properties:
time:
type: string
format: date-time
description: "date-time of the request"
off:
type: integer
description: "index 0 based offset of list data"
default: 0
len:
type: integer
description: "overall amount of items returned"
default: -1
data:
$ref: "#/definitions/InfoItem"
ListingItem:
type: integer
description: "ID of the referenced item"
InfoItem:
type: object
properties:
id:
type: string
text:
type: string
Based on #Anthon's answer it came to my mind that this is somewhat the construct I would need. Actually it is inheriting from a 'template':
...
templates:
AbstractBasicResponse:
properties:
time:
type: string
format: date-time
description: "date-time of the request"
off:
type: integer
description: "index 0 based offset of list data"
default: 0
len:
type: integer
description: "overall amount of items returned"
default: -1
definitions:
Items:
type: object
extends: AbstractBasicResponse
properties:
data:
type: array
items:
$ref: "#/definitions/ListingItem"
Item:
type: object
extends: AbstractBasicResponse
properties:
data:
$ref: "#/definitions/InfoItem"
ListingItem:
type: integer
description: "ID of the referenced item"
InfoItem:
type: object
properties:
id:
type: string
text:
type: string
...
You might not have to revert to full templating, there are two things within YAML that help with "undoubling" recurring data: anchors/aliases and merge keys.
An example of an anchor (introduced by &) referenced by an alias (*) would be:
definitions:
Items:
type: object
description: ""
properties:
time:
type: string
format: date-time
description: "date-time of the request"
off: &index
type: integer
description: "index 0 based offset of list data"
default: 0
len: &amount
type: integer
description: "overall amount of items returned"
default: -1
data:
type: array
items:
$ref: "#/definitions/ListingItem"
Item:
type: object
description: ""
properties:
time:
type: string
format: date-time
description: "date-time of the request"
off: *index
len: *amount
data:
A YAML parser needs to be able to handle this, but since the alias points to the same object after loading, the code using the data might no longer work the same because of side effect in some cases depending on how the loaded data is processed.
You can have multiple aliases referring to the same anchor.
The merge key (<<) is a special key in a mapping with which you can pre-load that mapping where it occurs with a bunch of key-value pairs. This is most effective when used with a anchor/alias. With that you you some finer control and you could do:
len: &altlen
type: integer
description: "overall amount of items returned"
default: -1
and then
len:
<<: &altlen
default: 42
Which would then be the same doing:
len:
type: integer
description: "overall amount of items returned"
default: 42
Merge keys are normally resolved at load time by the YAML parser, so there are no potential side-effects when using those even though they involve anchors and aliases.
i'm working on a RESTful API using swagger-api and swagger-editor for routes.
I can't figure out why the JSON i am sending through body, never reaches my controller.
here is my YAML
schemes:
- http
- https
produces: [application/json, multipart/form-data, application/x-www-form-urlencoded]
paths:
/projects:
x-swagger-router-controller: project
post:
description: create a new project
operationId: postProjects
consumes:
- application/json
parameters:
- name: param1
in: body
description: description
required: false
schema:
$ref: "#/definitions/Project"
responses:
"200":
description: Success
schema:
$ref: "#/definitions/Project"
default:
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
definitions:
Project:
properties:
name:
type: string
required:
- name
an example of the post request i'm sending.
curl -v -X POST -H "Content-Type: application/json" -d '{"name":"test"}' http://127.0.0.1:10010/projects
and the response
{"message":"Request validation failed: Parameter (param1) failed schema validation","code":"SCHEMA_VALIDATION_FAILED","failedValidation":true,"results":{"errors":[{"code":"OBJECT_MISSING_REQUIRED_PROPERTY","message":"Missing required property: name","path":[]}],"warnings":[]},"path":["paths","/projects","post","parameters","0"],"paramName":"param1"}
If i set the parameter "name" as not required, i just received an empty response like this
{ param1:
{ path: [ 'paths', '/projects', 'post', 'parameters', '0' ],
schema:
{ name: 'param1',
in: 'body',
description: 'description',
required: false,
schema: [Object] },
originalValue: {},
value: {} } }
I have no clue why since other format such as header, path or formdata works fine.
I always receive an empty object. req.swagger.params has no value.
I tried several schema but even the simplest is not working.
i can tell from the header that 'content-type': 'application/json'.
So the content type is set, the schema validates a simple string argument named "name". Everything should be ok. but still not.
This issue has been fixed.
It wasn't swagger related.
I built an API with nodeJs and i realized i didn't have a middleware to handle body parameter.
So because i missed a step before enabled the swagger middleware, i couldn't do anything with body parameter.
The main reason behind getting null values when sending json data to the API backend is the paramater path most of the time you give and the naming you give the parameter.
You also have to declare explicitly the type of schema you expect
You have to set parameter name to body and set in: body so that it picks the body object as a JSON
An example is here. You can try it out
/auth/register:
post:
tags:
- Auth
parameters:
- in: body
name: user
description: Create a new user.
schema:
type: object
required:
- firstName
- lastName
- email
- password
- confirmPassword
properties:
firstName:
type: string
lastName:
type: string
email:
type: string
password:
type: string
confirmPassword:
type: string
example:
firstName: Jane
lastName: Doe
email: janedoe#gmail.com
password: pass
confirmPassword: pass
responses:
"200":
description: OK
I try to specify the response from GET method with Swagger Editor.
But when I look in Swagger UI, the response JSON doesn't show.
My declaration swagger :
/clients/{id}:
get:
consumes:
- application/hal+json
produces:
- application/hal+json
# This is array of GET operation parameters:
parameters:
# An example parameter that is in query and is required
- name: id
in: path
required: true
type: string
# Expected responses for this operation:
responses:
# Response code
200:
description: Succes
# A schema describing your response object.
# Use JSON Schema format
schema:
example:
application/json: |
- {"produits":[{"idOffre":{"codeBanque":"038","identifiant":"123"},"idProduit":{"codeBanque":"061","identifiant":"123"}},{"idOffre":{"code":"038","identifiant":"123"},"idProduit":{"code":"061","identifiant":"123"}}]}
.....
In Swagger UI , the box where is written Response Class (Status 200) > Model Schema there is an empty json like that -> {}
I'm not sure swagger-ui supports examples, however I fixed some errors in you swagger extract:
example renamed examples
examples at same indentation level as schema (in you example, example is processed as a property of the response schema, I'm not sure this is what you want)
schema must describe response model, complete TODO
Fixed version:
swagger: '2.0'
info:
title: Clients
description: API
version: "1.0.0"
host: api.test.com
schemes:
- https
basePath: /v1
produces:
- application/json
paths:
/clients/{id}:
get:
consumes:
- application/hal+json
produces:
- application/hal+json
parameters:
- name: id
in: path
required: true
type: string
responses:
200:
description: Succes
schema:
type: array
items:
properties:
produits:
type: string
description: TODO
examples:
application/json: |
- {"produits":[{"idOffre":{"codeBanque":"038","identifiant":"123"},"idProduit":{"codeBanque":"061","identifiant":"123"}},{"idOffre":{"code":"038","identifiant":"123"},"idProduit":{"code":"061","identifiant":"123"}}]}