Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: parse request body for http SEARCH requests #4298

Merged
merged 2 commits into from Sep 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/Reference/Routes.md
Expand Up @@ -41,8 +41,8 @@ fastify.route(options)
need to be in [JSON Schema](https://json-schema.org/) format, check
[here](./Validation-and-Serialization.md) for more info.

* `body`: validates the body of the request if it is a POST, PUT, or PATCH
method.
* `body`: validates the body of the request if it is a POST, PUT, PATCH,
TRACE, or SEARCH method.
* `querystring` or `query`: validates the querystring. This can be a complete
JSON Schema object, with the property `type` of `object` and `properties`
object of parameters, or simply the values of what would be contained in the
Expand Down
4 changes: 2 additions & 2 deletions lib/handleRequest.js
Expand Up @@ -18,14 +18,14 @@ function handleRequest (err, request, reply) {
const method = request.raw.method
const headers = request.headers

if (method === 'GET' || method === 'HEAD' || method === 'SEARCH') {
if (method === 'GET' || method === 'HEAD') {
handler(request, reply)
return
}

const contentType = headers['content-type']

if (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'TRACE') {
if (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'TRACE' || method === 'SEARCH') {
if (contentType === undefined) {
if (
headers['transfer-encoding'] === undefined &&
Expand Down
199 changes: 169 additions & 30 deletions test/search.test.js
@@ -1,54 +1,63 @@
'use strict'

const t = require('tap')
const sget = require('simple-get').concat
const test = t.test
const fastify = require('..')()

const schema = {
schema: {
response: {
'2xx': {
type: 'object',
properties: {
hello: {
type: 'string'
}
response: {
'2xx': {
type: 'object',
properties: {
hello: {
type: 'string'
}
}
}
}
}

const querySchema = {
schema: {
querystring: {
type: 'object',
properties: {
hello: {
type: 'integer'
}
querystring: {
type: 'object',
properties: {
hello: {
type: 'integer'
}
}
}
}

const paramsSchema = {
schema: {
params: {
type: 'object',
properties: {
foo: {
type: 'string'
},
test: {
type: 'integer'
}
params: {
type: 'object',
properties: {
foo: {
type: 'string'
},
test: {
type: 'integer'
}
}
}
}

test('shorthand - search', t => {
const bodySchema = {
body: {
type: 'object',
properties: {
foo: {
type: 'string'
},
test: {
type: 'integer'
}
}
}
}

test('search', t => {
t.plan(1)
try {
fastify.route({
Expand All @@ -65,13 +74,13 @@ test('shorthand - search', t => {
}
})

test('shorthand - search params', t => {
test('search, params schema', t => {
t.plan(1)
try {
fastify.route({
method: 'SEARCH',
url: '/params/:foo/:test',
paramsSchema,
schema: paramsSchema,
handler: function (request, reply) {
reply.code(200).send(request.params)
}
Expand All @@ -82,13 +91,13 @@ test('shorthand - search params', t => {
}
})

test('shorthand - get, querystring schema', t => {
test('search, querystring schema', t => {
t.plan(1)
try {
fastify.route({
method: 'SEARCH',
url: '/query',
querySchema,
schema: querySchema,
handler: function (request, reply) {
reply.code(200).send(request.query)
}
Expand All @@ -98,3 +107,133 @@ test('shorthand - get, querystring schema', t => {
t.fail()
}
})

test('search, body schema', t => {
t.plan(1)
try {
fastify.route({
method: 'SEARCH',
url: '/body',
schema: bodySchema,
handler: function (request, reply) {
reply.code(200).send(request.body)
}
})
t.pass()
} catch (e) {
t.fail()
}
})

fastify.listen({ port: 0 }, err => {
t.error(err)
t.teardown(() => { fastify.close() })

const url = `http://localhost:${fastify.server.address().port}`

test('request - search', t => {
t.plan(4)
sget({
method: 'SEARCH',
url
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(response.headers['content-length'], '' + body.length)
t.same(JSON.parse(body), { hello: 'world' })
})
})

test('request search params schema', t => {
t.plan(4)
sget({
method: 'SEARCH',
url: `${url}/params/world/123`
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(response.headers['content-length'], '' + body.length)
t.same(JSON.parse(body), { foo: 'world', test: 123 })
})
})

test('request search params schema error', t => {
t.plan(3)
sget({
method: 'SEARCH',
url: `${url}/params/world/string`
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 400)
t.same(JSON.parse(body), {
error: 'Bad Request',
message: 'params/test must be integer',
statusCode: 400
})
})
})

test('request search querystring schema', t => {
t.plan(4)
sget({
method: 'SEARCH',
url: `${url}/query?hello=123`
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(response.headers['content-length'], '' + body.length)
t.same(JSON.parse(body), { hello: 123 })
})
})

test('request search querystring schema error', t => {
t.plan(3)
sget({
method: 'SEARCH',
url: `${url}/query?hello=world`
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 400)
t.same(JSON.parse(body), {
error: 'Bad Request',
message: 'querystring/hello must be integer',
statusCode: 400
})
})
})

test('request search body schema', t => {
t.plan(4)
const replyBody = { foo: 'bar', test: 5 }
sget({
method: 'SEARCH',
url: `${url}/body`,
body: JSON.stringify(replyBody),
headers: { 'content-type': 'application/json' }
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(response.headers['content-length'], '' + body.length)
t.same(JSON.parse(body), replyBody)
})
})

test('request search body schema error', t => {
t.plan(4)
sget({
method: 'SEARCH',
url: `${url}/body`,
body: JSON.stringify({ foo: 'bar', test: 'test' }),
headers: { 'content-type': 'application/json' }
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 400)
t.equal(response.headers['content-length'], '' + body.length)
t.same(JSON.parse(body), {
error: 'Bad Request',
message: 'body/test must be integer',
statusCode: 400
})
})
})
})