Skip to content

Commit

Permalink
feat: parse request body for http SEARCH requests (#4298)
Browse files Browse the repository at this point in the history
  • Loading branch information
kalvenschraut committed Sep 23, 2022
1 parent 8e985b4 commit 2c97c4c
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 34 deletions.
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
})
})
})
})

0 comments on commit 2c97c4c

Please sign in to comment.