From aa496a9b1395839b9c4b7024375deda64d8c3f26 Mon Sep 17 00:00:00 2001 From: KaKa Date: Sat, 30 Jan 2021 17:19:50 +0800 Subject: [PATCH] Fix swagger nxx response (#345) --- README.md | 28 +++++++++++++++++ lib/spec/openapi/utils.js | 11 ++++--- lib/spec/swagger/utils.js | 16 +++++++--- test/spec/openapi/schema.js | 32 +++++++++++++++++++ test/spec/swagger/schema.js | 61 +++++++++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f83ca999..d61515f1 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,34 @@ fastify.ready(err => { | openapi | {} | Openapi configuration. | | transform | null | Transform method for schema. | +##### 2XX status code +`fastify` itself support the `2xx`, `3xx` status, however `swagger` itself do not support this featuer. We will help you to transform the `2xx` status code into `200` and we will omit `2xx` status code when you already declared `200` status code. +Note: `openapi` will not be affected as it support the `2xx` syntax. + +Example: +```js +{ + response: { + '2xx': { + description: '2xx' + type: 'object' + } + } +} + +// it will becomes below +{ + response: { + 200: { + schema: { + description: '2xx' + type: 'object' + } + } + } +} +``` + ##### static `static` mode should be configured explicitly. In this mode `fastify-swagger` serves given specification, you should craft it yourself. ```js diff --git a/lib/spec/openapi/utils.js b/lib/spec/openapi/utils.js index a1af9520..0567217e 100644 --- a/lib/spec/openapi/utils.js +++ b/lib/spec/openapi/utils.js @@ -163,12 +163,15 @@ function resolveResponse (fastifyResponseJson, produces, ref) { const responsesContainer = {} - Object.keys(fastifyResponseJson).forEach(key => { - // 2xx is not supported by swagger + const statusCodes = Object.keys(fastifyResponseJson) - const rawJsonSchema = fastifyResponseJson[key] + statusCodes.forEach(statusCode => { + const rawJsonSchema = fastifyResponseJson[statusCode] const resolved = transformDefsToComponents(ref.resolve(rawJsonSchema)) + // 2xx require to be all upper-case + statusCode = statusCode.toUpperCase() + const content = {} if ((Array.isArray(produces) && produces.length === 0) || typeof produces === 'undefined') { @@ -181,7 +184,7 @@ function resolveResponse (fastifyResponseJson, produces, ref) { } }) - responsesContainer[key] = { + responsesContainer[statusCode] = { content, description: rawJsonSchema.description || 'Default Response' } diff --git a/lib/spec/swagger/utils.js b/lib/spec/swagger/utils.js index e230bc20..f0eb7fff 100644 --- a/lib/spec/swagger/utils.js +++ b/lib/spec/swagger/utils.js @@ -179,13 +179,21 @@ function resolveResponse (fastifyResponseJson, ref) { const responsesContainer = {} - Object.keys(fastifyResponseJson).forEach(key => { - // 2xx is not supported by swagger + const statusCodes = Object.keys(fastifyResponseJson) - const rawJsonSchema = fastifyResponseJson[key] + statusCodes.forEach(statusCode => { + const rawJsonSchema = fastifyResponseJson[statusCode] const resolved = ref.resolve(rawJsonSchema) - responsesContainer[key] = { + // 2xx is not supported by swagger + const deXXStatusCode = statusCode.toUpperCase().replace('XX', '00') + // conflict when we have both 2xx and 200 + if (statusCode.toUpperCase().includes('XX') && statusCodes.includes(deXXStatusCode)) { + return + } + statusCode = deXXStatusCode + + responsesContainer[statusCode] = { schema: resolved, description: rawJsonSchema.description || 'Default Response' } diff --git a/test/spec/openapi/schema.js b/test/spec/openapi/schema.js index b04aa063..401cf320 100644 --- a/test/spec/openapi/schema.js +++ b/test/spec/openapi/schema.js @@ -40,3 +40,35 @@ test('suport - oneOf, anyOf, allOf', t => { }) }) }) + +test('support 2xx response', async t => { + const opt = { + schema: { + response: { + '2XX': { + type: 'object' + }, + '3xx': { + type: 'object' + } + } + } + } + + const fastify = Fastify() + fastify.register(fastifySwagger, { + openapi: true, + routePrefix: '/docs', + exposeRoute: true + }) + fastify.get('/', opt, () => {}) + + await fastify.ready() + + const swaggerObject = fastify.swagger() + const api = await Swagger.validate(swaggerObject) + + const definedPath = api.paths['/'].get + t.same(definedPath.responses['2XX'].description, 'Default Response') + t.same(definedPath.responses['3XX'].description, 'Default Response') +}) diff --git a/test/spec/swagger/schema.js b/test/spec/swagger/schema.js index ab2ef6ef..8aa0bff6 100644 --- a/test/spec/swagger/schema.js +++ b/test/spec/swagger/schema.js @@ -100,3 +100,64 @@ test('response default description', async t => { const definedPath = api.paths['/'].get t.same(definedPath.responses['200'].description, 'Default Response') }) + +test('response 2xx', async t => { + const opt = { + schema: { + response: { + '2xx': { + type: 'object' + } + } + } + } + + const fastify = Fastify() + fastify.register(fastifySwagger, { + routePrefix: '/docs', + exposeRoute: true + }) + fastify.get('/', opt, () => {}) + + await fastify.ready() + + const swaggerObject = fastify.swagger() + const api = await Swagger.validate(swaggerObject) + + const definedPath = api.paths['/'].get + t.same(definedPath.responses['200'].description, 'Default Response') + t.notOk(definedPath.responses['2XX']) +}) + +test('response conflict 2xx and 200', async t => { + const opt = { + schema: { + response: { + '2xx': { + type: 'object', + description: '2xx' + }, + 200: { + type: 'object', + description: '200' + } + } + } + } + + const fastify = Fastify() + fastify.register(fastifySwagger, { + routePrefix: '/docs', + exposeRoute: true + }) + fastify.get('/', opt, () => {}) + + await fastify.ready() + + const swaggerObject = fastify.swagger() + const api = await Swagger.validate(swaggerObject) + + const definedPath = api.paths['/'].get + t.same(definedPath.responses['200'].description, '200') + t.notOk(definedPath.responses['2XX']) +})