Closed PatrickHeneise closed 3 years ago
What does it mean “it works”? @Eomm is the master of shared schemas, he might take a look here as well.
Using "bar#" (which is not a common/shared schema) works. Shared schema doesn't.
This should work (with last fast-json-stringify
installed):
response: {
200: {$ref: 'https://foo/common.json#bar'}
}
When you write someId#
(hash at the end) you are using the "replace way" of the shared schema feature, but if you write the $ref as you did, you are using the $ref-way
so you need to use the standard schema definition.
I thought I tested that case and it didn't work, but I'll try again in the morning.
response: {
200: { $ref: 'https://foo/common.js#bar' }
}
UnhandledPromiseRejectionWarning: TypeError: Cannot read property '$ref' of undefined
Looking here: https://github.com/fastify/fastify-swagger/blob/c41d37cd4a2ceb6b1a667f3dd03f8ccf5f53e2bf/dynamic.js#L96
Maybe, the shared schemas are not provided to swagger.
I can't go deeper now, could you check it?
when using 'bar#', the schema is transformed to an object, with the ref it's not.
I've decided to move forward with multiple schema files instead of common.json.
Going back and forth experimenting with the schemas. I found some inconsistencies:
works:
body: { $ref: '/foo.json#/definitions/bar' }
fails:
response: {
200: { $ref: '/foo.json#/definitions/bar' }
}
TypeError: Cannot read property '$ref' of undefined
in fast-json-stringify/index.js:485:15
Then I tried
response: {
200: '/foo.json#/definitions/bar'
}
Error: schema is invalid: data should be object,boolean
in fast-json-stringify/index.js:30:17
Yeah, that doesn't surprise me:
For the trouble:
200: { $ref: '/foo.json#/definitions/bar' }
=> I think this should work, could you share your npm ls
?200: '/foo.json#/definitions/bar'
=> it is correct that it throw error since it is not validIt's a long list ... I selected the path that might be the one you're looking for:
├─┬ fastify@2.3.0
│ ├── ajv@6.10.0 deduped
│ ├── UNMET DEPENDENCY ajv-merge-patch@^4.1.0
│ ├─┬ fast-json-stringify@1.15.2
│ │ ├── ajv@6.10.0 deduped
started the project from scratch, so the dependencies should all be up-to-date.
If you point me into the direction, I'm happy to help fix this, as I need it in my current project.
Sorry @PatrickHeneise , I missed your comment. Did you solve meanwhile?
Otherwise, I will check this problem in next days
No, I worked around the issue by placing the schema I need in /index.js
and reference from there, but it's not pretty.
I've almost the same problem. The swagger doesn't recognize some shared schemas. Here is a repo with reproducing of error.
There are 4 routes: GET /api/auth -> works fine, 'cause I wrap my shared schema in additional property "userSource" GET /api/chats/ -> is ok with shared schema
GET /api/auth-broken -> fails in UI with Could not resolve reference: undefined undefined PUT /api/chats/{chatId}/messages -> fails in UI like a previous [despite of wrapping]
Are there any ways to avoid this? Or should we waiting for fixing?
Came across the same issue today.
This works, when the response is of type array
response: {
200: {
description: 'Successful response',
type: 'array',
items: {
$ref: '#Journal',
},
},
},
But this doesn't work when response is an object. I don't know if this is the intended behaviour.
response: {
200: {
description: 'Successful response',
type: 'object',
$ref: '#Journal',
},
},
As a workaround, I used fastify
instance to pull the already compiled schema and it works as expected:
Option 1.
response: {
200: {
description: 'Successful response',
type: 'object',
...(fastify.getSchema('#Journal') as object), // silence typescript
},
},
Option 2.
response: {
200: fastify.getSchema('#Journal')
},
Does anybody here have a full example of referencing the models from dynamic routes the Swagger way?
"responses": {
"500": {
"schema": {
"$ref": "#/definitions/ErrorModel"
}
}
}
I've tried to put "definitions" into their place in the plugin options, but that did not work. Should it be a separate feature request?
So when I did
addSchema({
$id: 'shared',
definitions
});
then this response definition does not blow up fastify
500: {
$ref: 'shared#/definitions/ErrorResponse'
}
However, in this case the schema is nested and the path is transformed in output: "500":{"schema":{"$ref":"#/definitions/def-0/definitions/ErrorResponse"}
which violates Swagger spec as definitions object must not be nested https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#definitionsObject
Coud somebody share an example of multiple responses? Eg. I want to define both 404 & 500 objects in a single shared definition. Eg. $ref: 'shared#/definitions/responses'
. Example:
fastify.addSchema({
$id: 'shared',
type: 'object',
definitions: {
responses: {
type: 'array',
properties: {
404: {
description: 'Not Found',
type: 'object',
properties: {
message: { type: 'string' },
},
example: {
message: 'Not found',
}
},
500: {
description: 'Internal Server Error',
type: 'object',
properties: {
message: { type: 'string' },
},
example: {
message: 'Unknown column....',
}
}
}
}
}
And use multiple responses in an schema:
// Example schema
{
description: 'Example',
response: {
200: {
description: 'Successful response',
type: 'object',
properties: {
user_id: { type: 'number' },
user_name: { type: 'string' },
user_mail_address: { type: 'string' }
},
// And then use the shared responses (multiple)
$ref: 'shared#/definitions/responses',
}
}
}
Too bad this doesn't work.. But it would be very cool, if it actually did work like this.
Using:
fastify.addSchema({
$id: 'shared',
type: 'object',
definitions: {
internalServerErrorResponse: {
type: 'object',
description: '500 Internal Server Error',
properties: {
message: {
type: 'string',
description: 'Error message',
example: 'Some internal error message'
}
}
}
}
})
And then use the shared definition:
500: {
$ref: 'shared#/definitions/internalServerErrorResponse'
}
I will get:
OpenAPI v3 component responses also doesn't work in Fastify Swagger, so I created a ticket for that: https://github.com/fastify/fastify-swagger/issues/793
Now I'm using addSchema
without definitions, but only a top level ID:
fastify.addSchema({
$id: 'internalServerErrorResponse',
type: 'object',
description: '500 Internal Server Error',
properties: {
message: {
type: 'string',
description: 'Error message',
example: 'Some internal error message'
}
}
})
Then use it in your schema like this:
schema: {
description: 'example',
response: {
500: {
$ref: 'internalServerErrorResponse#'
}
}
}
This ALMOST works.. Except the description message still says "Default Response" in Swagger UI:
I use a shared schema:
And trying to use that schema in the response validation:
It works perfectly fine in a list/index route:
but not for get /:id
I'm trying to track down the issue but would appreciate a hint to where to start. Everything works fine if I add the schema "bar" individually before: