Skip to content

Commit

Permalink
fix: return the correct serializer function when no content-type is d…
Browse files Browse the repository at this point in the history
…efined (#5229)

* fix: `npm run test:watch` (#5221)

* fix: set default content type to get a serializer from

* feat: add tests

* feat: add tests

* fix: schema for the test

* feat: translate word to English

* fix: change the name of the test

* feat: make it return false when not a function

* chore: undo last changes

* feat: make the content-type definition cleaner

* fix: nullish coalescing assignment is not supported in node 14

Co-authored-by: Aras Abbasi <aras.abbasi@googlemail.com>
Signed-off-by: Douglas Moura <douglas.ademoura@gmail.com>

* fix: rename test to kebab-case

* feat: improve tests

* feat: remove t.end in favor of t.plan

---------

Signed-off-by: Douglas Moura <douglas.ademoura@gmail.com>
Co-authored-by: Adam Jones <domdomegg+git@gmail.com>
Co-authored-by: Aras Abbasi <aras.abbasi@googlemail.com>
  • Loading branch information
3 people committed Dec 28, 2023
1 parent 4e29783 commit 8c0140a
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/error-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ function defaultErrorHandler (error, request, reply) {
function fallbackErrorHandler (error, reply, cb) {
const res = reply.raw
const statusCode = reply.statusCode
reply[kReplyHeaders]['content-type'] = reply[kReplyHeaders]['content-type'] ?? 'application/json; charset=utf-8'
let payload
try {
const serializerFn = getSchemaSerializer(reply[kRouteContext], statusCode, reply[kReplyHeaders]['content-type'])
Expand All @@ -121,7 +122,6 @@ function fallbackErrorHandler (error, reply, cb) {
payload = serializeError(new FST_ERR_REP_INVALID_PAYLOAD_TYPE(typeof payload))
}

reply[kReplyHeaders]['content-type'] = 'application/json; charset=utf-8'
reply[kReplyHeaders]['content-length'] = '' + Buffer.byteLength(payload)

cb(reply, payload)
Expand Down
187 changes: 187 additions & 0 deletions test/serialize-response.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
'use strict'

const t = require('tap')
const test = t.test
const { S } = require('fluent-json-schema')
const Fastify = require('../fastify')
const sjson = require('secure-json-parse')

const BadRequestSchema = S.object()
.prop('statusCode', S.number())
.prop('error', S.string())
.prop('message', S.string())

const InternalServerErrorSchema = S.object()
.prop('statusCode', S.number())
.prop('error', S.string())
.prop('message', S.string())

const NotFoundSchema = S.object()
.prop('statusCode', S.number())
.prop('error', S.string())
.prop('message', S.string())

const options = {
schema: {
body: {
type: 'object',
properties: {
id: { type: 'string' }
}
},
response: {
200: {
type: 'object',
properties: {
id: { type: 'string' }
}
},
400: {
description: 'Bad Request',
content: {
'application/json': {
schema: BadRequestSchema.valueOf()
}
}
},
404: {
description: 'Resource not found',
content: {
'application/json': {
schema: NotFoundSchema.valueOf(),
example: {
statusCode: 404,
error: 'Not Found',
message: 'Not Found'
}
}
}
},
500: {
description: 'Internal Server Error',
content: {
'application/json': {
schema: InternalServerErrorSchema.valueOf(),
example: {
message: 'Internal Server Error'
}
}
}
}
}
}
}

const handler = (request, reply) => {
if (request.body.id === '400') {
return reply.status(400).send({
statusCode: 400,
error: 'Bad Request',
message: 'Custom message',
extra: 'This should not be in the response'
})
}

if (request.body.id === '404') {
return reply.status(404).send({
statusCode: 404,
error: 'Not Found',
message: 'Custom Not Found',
extra: 'This should not be in the response'
})
}

if (request.body.id === '500') {
reply.status(500).send({
statusCode: 500,
error: 'Internal Server Error',
message: 'Custom Internal Server Error',
extra: 'This should not be in the response'
})
}

reply.send({
id: request.body.id,
extra: 'This should not be in the response'
})
}

test('serialize the response for a Bad Request error, as defined on the schema', async t => {
t.plan(2)

const fastify = Fastify({})

fastify.post('/', options, handler)
const response = await fastify.inject({
method: 'POST',
url: '/'
})

t.equal(response.statusCode, 400)
t.same(sjson(response.body), {
statusCode: 400,
error: 'Bad Request',
message: 'body must be object'
})
})

test('serialize the response for a Not Found error, as defined on the schema', async t => {
t.plan(2)

const fastify = Fastify({})

fastify.post('/', options, handler)

const response = await fastify.inject({
method: 'POST',
url: '/',
body: { id: '404' }
})

t.equal(response.statusCode, 404)
t.same(sjson(response.body), {
statusCode: 404,
error: 'Not Found',
message: 'Custom Not Found'
})
})

test('serialize the response for a Internal Server Error error, as defined on the schema', async t => {
t.plan(2)

const fastify = Fastify({})

fastify.post('/', options, handler)

const response = await fastify.inject({
method: 'POST',
url: '/',
body: { id: '500' }
})

t.equal(response.statusCode, 500)
t.same(sjson(response.body), {
statusCode: 500,
error: 'Internal Server Error',
message: 'Custom Internal Server Error'
})
})

test('serialize the success response, as defined on the schema', async t => {
t.plan(2)

const fastify = Fastify({})

fastify.post('/', options, handler)

const response = await fastify.inject({
method: 'POST',
url: '/',
body: { id: 'test' }
})

t.equal(response.statusCode, 200)
t.same(sjson(response.body), {
id: 'test'
})
})

0 comments on commit 8c0140a

Please sign in to comment.