This is a simplified version of my OpenAPI 3.0 definition I'm viewing on the Swagger Editor online. I am trying to have the two responses for error codes 401 and 403, that share the same schema, show different examples - this doesn't seem to work and I still see the referenced type as example.
Can you help me figuring out what's wrong with the definitions?
openapi: 3.0.0
info:
version: '1.0'
title: A service
paths:
/doSomething:
post:
requestBody:
content:
application/json:
schema:
type: string
example: A string
responses:
401:
$ref: '#/components/responses/Unauthorized'
403:
$ref: '#/components/responses/Denied'
components:
responses:
Unauthorized:
description: The endpoint cannot be reached because the request is not authorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: unauthorized
Denied:
description: The request's authorizations don't match the required ones needed to access the resource
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: permissions denied
schemas:
Error:
type: object
properties:
error:
type: string
Your definition is correct, and the response example show up in Swagger Editor 3.6.5+ and Swagger UI 3.17.4+. Also, multiple examples are supported in Swagger UI 3.23.0+ and Editor 3.6.31+.
I am not sure whether this is at the heart of your problem but I noticed that the HTTP status codes in your path respone sections aren't given enclosed in quotation marks. The OpenAPI specification v3.x (in contrast to v2.x) makes this mandatory which you might want to look up here:
https://swagger.io/specification/#responses-object
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#responses-object
Related
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
I defined my authentication in security and components/securitySchemes.
In the Swagger documentation about response, they provide this example:
paths:
/something:
get:
...
responses:
...
'401':
$ref: '#/components/responses/UnauthorizedError'
post:
...
responses:
...
'401':
$ref: '#/components/responses/UnauthorizedError'
...
components:
responses:
UnauthorizedError:
description: Authentication information is missing or invalid
headers:
WWW_Authenticate:
schema:
type: string
I have a lot more paths than two, and to access any of them, the client has to be authenticated. I would like to avoid the '401' definition for each path, and define it once globally, if it is possible somehow.
How is it possible to use this response for each path?
'401':
$ref: '#/components/responses/UnauthorizedError'
You can't, if you want the response to show up on that particular endpoint.
I avoid the repetition in favour of important errors by not adding them to each endpoint and instead putting the well understood standard responses - 401, 403, 429, 404, 503 - on either a status endpoint or on the root method. eg:
'/{foo}/{bar}/status':
get:
tags:
- api
responses:
'200':
description: successful response with a resource
content:
application/json:
schema:
$ref: '#/components/schemas/statusResponse'
'400':
$ref: '#/components/responses/400_error_response'
'401':
$ref: '#/components/responses/401_error_response'
'403':
$ref: '#/components/responses/403_error_response'
'404':
$ref: '#/components/responses/404_error_response'
'500':
$ref: '#/components/responses/500_error_response'
The boilerplate responses would then all refer to the standard responses.
Real endpoints then typically have a well defined response specific to that opearation and the things that may go specifically wrong.
'/{foo}/{bar}/segment':
post:
summary: checks username is found or not
description: |-
checks username and returns 204 if found else 403
operationId: checkUsername
tags:
- Login
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/segment_POST_request'
responses:
'200':
$ref: '#/components/responses/segment_POST_200_response'
'403':
$ref: '#/components/responses/403_forbidden_response'
'500':
$ref:
'#/components/responses/500_internal_server_error_replayable_response'
One thing I ensure is for error responses, the possible error codes for that operation are included in the response, like so:
500_internal_server_error_replayable_response:
description: |-
The following `500 Internal Server Error` errors can occur during the API processing.
| errorCode | cause | details |
| - | - | - |
| `SOME.ERROR.500` | There was an error processing the request either in Foo or on a downstream system | A request to something failed, Bar or Baz however the error is recoverable and can be replayed |
| `SOME.ERROR.014` | Baz returned a `404` during the migration operation, even though it has previously confirmed the member exists | This is a fatal error during the migration process and cannot be recovered. The request should not be replayed. |
headers:
content:
application/json:
schema:
$ref: '#/components/schemas/errorResponse'
example:
status: '500'
errorCode: SOME.ERROR.500
errorDescription: The request could not be processed
errorSubCode: ''
furtherDetails: ''
docLink: ''
Use an extension to add them in automatically as part of your build script.
What you're looking to do is not part of the OpenAPI standard. Responses are not inherited from parent objects; they must be explicitly added to every endpoint. You can include a $ref for each response, but with a well-defined spec with lots of endpoints, you'll end up with a lot of duplication, and it's likely an endpoint might miss a response or two over time as additions and modifications are made. Plus, it's simply not a good authoring experience.
To prevent this problem, add an extension to your responses, like this:
responses:
x-default-responses: true
'418':
description: Additional responses go here
The above spec will be the one that you work from. When done, have a script scan your completed yaml file, and replace that line with your list of default responses. Use this modified spec as the next stage of your development process (whatever it is you're using your OpenAPI spec for, be it documentation, testing, or SDK generation).
While you could have your script add the responses without the extension property (after all, it is just YAML you're writing), I recommend you don't do this. The extension makes your intent clear, so other editors will understand additional responses are present. Additionally, it is likely that (either now or one day in the future) you will have endpoints that do not conform to your default responses, so you wouldn't want to accidentally add those.
I am creating a well-organized OAS3 swagger documentation on swaggerhub. For every endpoint i am writing all possible answers like 200, 201, 204, 400, 401, 403, 404, 500 etc. In addition all methods have default parameters like X-Language-Code etc.
I am in such a place that the responses, models, parameters I use now begin to repeat themselves in each file. After a little research i learnt that i can create a domain and remote absolute url references to them.
There is no error when i used the 'definition's remotely like this:
/example:
get:
#some other informations here
responses:
200:
description: 'example description'
content:
application/json:
schema:
$ref: 'https://remote.example/url/2.0#/definitions/ExampleResponse'
But, apparently you can not use $ref keyword right below responses or 400 etc.. keyword like this:
This one not getting error but not rendering the remote reference
responses:
400:
$ref: 'https://remote.example/url/2.0#/responses/Error400'
or this:
This one gives error
responses:
$ref: 'https://remote.example/url/2.0#/responses'
Even, i can not use 'parameters' as i expected:
/example:
get:
parameters:
- languageCode:
$ref: 'https://remote.example/url/2.0#/parameters/languageCode'
/example:
get:
parameters:
- $ref: 'https://remote.example/url/2.0#/parameters/'
I dont want to rewrite all reference definitions below every documentation.
I am confused about using and referencing 'domain's. Can someone explain or referencing a document about this situations since i couldn't found any documentation about it.
Update: OpenAPI 3.0 domains are now supported in SwaggerHub.
As of December 2018, SwaggerHub domains only support the OpenAPI 2.0 syntax but not OpenAPI 3.0. OpenAPI 3.0 and 2.0 use slightly different syntax for parameters, responses, etc., this means you cannot reference an OAS2 domain from an OAS3 API definition.
The workaround is to create another OpenAPI 3.0 API in SwaggerHub and use it as a "domain". You'll need to add a dummy header with openapi: 3.0.0, the info section and empty paths: {} to make the validator happy.
openapi: 3.0.0
info:
title: Common components
version: 1.0.0
paths: {}
# Put your common components here:
components:
schemas:
...
parameters:
...
responses:
...
Then you can reference components from this "domain" using the usual $ref syntax:
$ref: 'https://api.swaggerhub.com/apis/USERNAME/API-NAME/VERSION#/components/responses/Error400'
Make sure the hostname in $refs is API.swaggerhub.com (not APP.swaggerhub.com) and the link contains /apis/ (not /domains/).
I am having problem with my OpenAPI spec file. I am trying to call an exposed url to 'GET' an id but every time i port forward the service to my local and then try to send request through API document my connection is refused. I would appreciate any help. The id that i am expecting would be in JSON format. Below is my spec file
openapi: "3.0.0"
info:
version: 1.0.0
title: Id Generator
servers:
url: www.someurl.com
paths:
/posts:
get:
summary: Get Id
operationId: id
tags:
- posts
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: "#/definition/Post"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/definition/Error"
definition:
Post:
type: object
properties:
id:
type: string
Error:
properties:
id:
type: string
As of June 21 2017, OpenAPI Specification 3.0 is not out yet and Swagger UI does not support OpenAPI 3.0 yet, so your example can't possibly work. Keep an eye on Swagger UI releases page to know when support for OpenAPI 3.0 is available.
Also, you'll need to fix the errors in your spec to make it a valid OpenAPI 3.0 spec:
servers is an array, so change that to:
servers:
- url: http://www.someurl.com
Response status codes must be quoted: "200" or '200'.
Indent the $ref under schemas:
schema:
$ref: "#/definition/Post"
...
schema:
$ref: "#/definition/Error"
Change definition to components->schemas and fix the indentation for Post:
components:
schemas:
Post:
type: object
properties:
id:
type: string
Error:
properties:
id:
type: string
I want almost all my paths to have the following 3 generic error responses. How do I describe that in Swagger without copypasting these lines everywhere?
401:
description: The requester is unauthorized.
schema:
$ref: '#/definitions/Error'
500:
description: "Something went wrong. It's server's fault."
schema:
$ref: '#/definitions/Error'
503:
description: Server is unavailable. Maybe there is maintenance?
schema:
$ref: '#/definitions/Error'
Example of how I use this in a request:
paths:
/roles:
get:
summary: Roles
description: |
Returns all roles available for users.
responses:
200:
description: An array with all roles.
schema:
type: array
items:
$ref: '#/definitions/Role'
401:
description: The requester is unauthorized.
schema:
$ref: '#/definitions/Error'
500:
description: "Something went wrong. It's server's fault."
schema:
$ref: '#/definitions/Error'
503:
description: Server is unavailable. Maybe there is maintenance?
schema:
$ref: '#/definitions/Error'
Looks like I can add the following global response definition:
# An object to hold responses that can be used across operations.
# This property does not define global responses for all operations.
responses:
NotAuthorized:
description: The requester is unauthorized.
schema:
$ref: '#/definitions/Error'
However I will still need to reference it in paths like this:
401:
$ref: '#/responses/NotAuthorized'
Same thing in OpenAPI 3.0, except it uses #/components/responses/... instead of #/responses/...:
openapi: 3.0.0
# An object to hold responses that can be used across operations.
# This property does not define global responses for all operations.
components:
responses:
NotAuthorized:
description: The requester is unauthorized.
schema:
$ref: '#/components/schemas/Error'
# Then, in operation responses, use:
...
401:
$ref: '#/components/responses/NotAuthorized'
There's also an open feature request in the OpenAPI Specification repository to add support for global/default responses for operations.