1 | 'use strict'
|
2 |
|
3 | const sget = require('simple-get').concat
|
4 | const stream = require('stream')
|
5 | const symbols = require('../lib/symbols')
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | module.exports.payloadMethod = function (method, t, isSetErrorHandler = false) {
|
13 | const test = t.test
|
14 | const fastify = require('..')()
|
15 |
|
16 | if (isSetErrorHandler) {
|
17 | fastify.setErrorHandler(function (err, request, reply) {
|
18 | t.type(request, 'object')
|
19 | t.type(request, fastify[symbols.kRequest])
|
20 | reply
|
21 | .code(err.statusCode)
|
22 | .type('application/json; charset=utf-8')
|
23 | .send(err)
|
24 | })
|
25 | }
|
26 |
|
27 | const upMethod = method.toUpperCase()
|
28 | const loMethod = method.toLowerCase()
|
29 |
|
30 | const schema = {
|
31 | schema: {
|
32 | response: {
|
33 | '2xx': {
|
34 | type: 'object',
|
35 | properties: {
|
36 | hello: {
|
37 | type: 'string'
|
38 | }
|
39 | }
|
40 | }
|
41 | }
|
42 | }
|
43 | }
|
44 |
|
45 | test(`${upMethod} can be created`, t => {
|
46 | t.plan(1)
|
47 | try {
|
48 | fastify[loMethod]('/', schema, function (req, reply) {
|
49 | reply.code(200).send(req.body)
|
50 | })
|
51 | t.pass()
|
52 | } catch (e) {
|
53 | t.fail()
|
54 | }
|
55 | })
|
56 |
|
57 | test(`${upMethod} without schema can be created`, t => {
|
58 | t.plan(1)
|
59 | try {
|
60 | fastify[loMethod]('/missing', function (req, reply) {
|
61 | reply.code(200).send(req.body)
|
62 | })
|
63 | t.pass()
|
64 | } catch (e) {
|
65 | t.fail()
|
66 | }
|
67 | })
|
68 |
|
69 | test(`${upMethod} with body and querystring`, t => {
|
70 | t.plan(1)
|
71 | try {
|
72 | fastify[loMethod]('/with-query', function (req, reply) {
|
73 | req.body.hello = req.body.hello + req.query.foo
|
74 | reply.code(200).send(req.body)
|
75 | })
|
76 | t.pass()
|
77 | } catch (e) {
|
78 | t.fail()
|
79 | }
|
80 | })
|
81 |
|
82 | test(`${upMethod} with bodyLimit option`, t => {
|
83 | t.plan(1)
|
84 | try {
|
85 | fastify[loMethod]('/with-limit', { bodyLimit: 1 }, function (req, reply) {
|
86 | reply.send(req.body)
|
87 | })
|
88 | t.pass()
|
89 | } catch (e) {
|
90 | t.fail()
|
91 | }
|
92 | })
|
93 |
|
94 | fastify.listen(0, function (err) {
|
95 | if (err) {
|
96 | t.error(err)
|
97 | return
|
98 | }
|
99 |
|
100 | fastify.server.unref()
|
101 |
|
102 | test(`${upMethod} - correctly replies`, t => {
|
103 | t.plan(3)
|
104 | sget({
|
105 | method: upMethod,
|
106 | url: 'http://localhost:' + fastify.server.address().port,
|
107 | body: {
|
108 | hello: 'world'
|
109 | },
|
110 | json: true
|
111 | }, (err, response, body) => {
|
112 | t.error(err)
|
113 | t.strictEqual(response.statusCode, 200)
|
114 | t.deepEqual(body, { hello: 'world' })
|
115 | })
|
116 | })
|
117 |
|
118 | test(`${upMethod} - correctly replies with very large body`, t => {
|
119 | t.plan(3)
|
120 |
|
121 | const largeString = 'world'.repeat(13200)
|
122 | sget({
|
123 | method: upMethod,
|
124 | url: 'http://localhost:' + fastify.server.address().port,
|
125 | body: { hello: largeString },
|
126 | json: true
|
127 | }, (err, response, body) => {
|
128 | t.error(err)
|
129 | t.strictEqual(response.statusCode, 200)
|
130 | t.deepEqual(body, { hello: largeString })
|
131 | })
|
132 | })
|
133 |
|
134 | test(`${upMethod} - correctly replies if the content type has the charset`, t => {
|
135 | t.plan(3)
|
136 | sget({
|
137 | method: upMethod,
|
138 | url: 'http://localhost:' + fastify.server.address().port,
|
139 | body: JSON.stringify({ hello: 'world' }),
|
140 | headers: {
|
141 | 'content-type': 'application/json; charset=utf-8'
|
142 | }
|
143 | }, (err, response, body) => {
|
144 | t.error(err)
|
145 | t.strictEqual(response.statusCode, 200)
|
146 | t.deepEqual(body.toString(), JSON.stringify({ hello: 'world' }))
|
147 | })
|
148 | })
|
149 |
|
150 | test(`${upMethod} without schema - correctly replies`, t => {
|
151 | t.plan(3)
|
152 | sget({
|
153 | method: upMethod,
|
154 | url: 'http://localhost:' + fastify.server.address().port + '/missing',
|
155 | body: {
|
156 | hello: 'world'
|
157 | },
|
158 | json: true
|
159 | }, (err, response, body) => {
|
160 | t.error(err)
|
161 | t.strictEqual(response.statusCode, 200)
|
162 | t.deepEqual(body, { hello: 'world' })
|
163 | })
|
164 | })
|
165 |
|
166 | test(`${upMethod} with body and querystring - correctly replies`, t => {
|
167 | t.plan(3)
|
168 | sget({
|
169 | method: upMethod,
|
170 | url: 'http://localhost:' + fastify.server.address().port + '/with-query?foo=hello',
|
171 | body: {
|
172 | hello: 'world'
|
173 | },
|
174 | json: true
|
175 | }, (err, response, body) => {
|
176 | t.error(err)
|
177 | t.strictEqual(response.statusCode, 200)
|
178 | t.deepEqual(body, { hello: 'worldhello' })
|
179 | })
|
180 | })
|
181 |
|
182 | test(`${upMethod} with no body - correctly replies`, t => {
|
183 | t.plan(6)
|
184 |
|
185 | sget({
|
186 | method: upMethod,
|
187 | url: 'http://localhost:' + fastify.server.address().port + '/missing',
|
188 | headers: { 'Content-Length': '0' }
|
189 | }, (err, response, body) => {
|
190 | t.error(err)
|
191 | t.strictEqual(response.statusCode, 200)
|
192 | t.strictEqual(JSON.parse(body.toString()), null)
|
193 | })
|
194 |
|
195 |
|
196 | fastify.inject({
|
197 | method: upMethod,
|
198 | url: '/missing'
|
199 | }, (err, res) => {
|
200 | t.error(err)
|
201 | t.strictEqual(res.statusCode, 200)
|
202 | t.strictEqual(JSON.parse(res.payload), null)
|
203 | })
|
204 | })
|
205 |
|
206 | test(`${upMethod} returns 415 - incorrect media type if body is not json`, t => {
|
207 | t.plan(2)
|
208 | sget({
|
209 | method: upMethod,
|
210 | url: 'http://localhost:' + fastify.server.address().port + '/missing',
|
211 | body: 'hello world'
|
212 |
|
213 | }, (err, response, body) => {
|
214 | t.error(err)
|
215 | if (upMethod === 'OPTIONS') {
|
216 | t.strictEqual(response.statusCode, 200)
|
217 | } else {
|
218 | t.strictEqual(response.statusCode, 415)
|
219 | }
|
220 | })
|
221 | })
|
222 |
|
223 | if (loMethod === 'options') {
|
224 | test('OPTIONS returns 415 - should return 415 if Content-Type is not json or plain text', t => {
|
225 | t.plan(2)
|
226 | sget({
|
227 | method: upMethod,
|
228 | url: 'http://localhost:' + fastify.server.address().port + '/missing',
|
229 | body: 'hello world',
|
230 | headers: {
|
231 | 'Content-Type': 'text/xml'
|
232 | }
|
233 | }, (err, response, body) => {
|
234 | t.error(err)
|
235 | t.strictEqual(response.statusCode, 415)
|
236 | })
|
237 | })
|
238 | }
|
239 |
|
240 | test(`${upMethod} returns 400 - Bad Request`, t => {
|
241 | t.plan(4)
|
242 |
|
243 | sget({
|
244 | method: upMethod,
|
245 | url: 'http://localhost:' + fastify.server.address().port,
|
246 | body: 'hello world',
|
247 | headers: {
|
248 | 'Content-Type': 'application/json'
|
249 | }
|
250 | }, (err, response, body) => {
|
251 | t.error(err)
|
252 | t.strictEqual(response.statusCode, 400)
|
253 | })
|
254 |
|
255 | sget({
|
256 | method: upMethod,
|
257 | url: 'http://localhost:' + fastify.server.address().port,
|
258 | headers: {
|
259 | 'Content-Type': 'application/json',
|
260 | 'Content-Length': '0'
|
261 | }
|
262 | }, (err, response, body) => {
|
263 | t.error(err)
|
264 | t.strictEqual(response.statusCode, 400)
|
265 | })
|
266 | })
|
267 |
|
268 | test(`${upMethod} returns 413 - Payload Too Large`, t => {
|
269 | t.plan(upMethod === 'OPTIONS' ? 4 : 6)
|
270 |
|
271 | sget({
|
272 | method: upMethod,
|
273 | url: 'http://localhost:' + fastify.server.address().port,
|
274 | headers: {
|
275 | 'Content-Type': 'application/json',
|
276 | 'Content-Length': 1024 * 1024 + 1
|
277 | }
|
278 | }, (err, response, body) => {
|
279 | t.error(err)
|
280 | t.strictEqual(response.statusCode, 413)
|
281 | })
|
282 |
|
283 |
|
284 | if (upMethod !== 'OPTIONS') {
|
285 | var chunk = Buffer.alloc(1024 * 1024 + 1, 0)
|
286 | const largeStream = new stream.Readable({
|
287 | read () {
|
288 | this.push(chunk)
|
289 | chunk = null
|
290 | }
|
291 | })
|
292 | sget({
|
293 | method: upMethod,
|
294 | url: 'http://localhost:' + fastify.server.address().port,
|
295 | headers: { 'Content-Type': 'application/json' },
|
296 | body: largeStream
|
297 | }, (err, response, body) => {
|
298 | t.error(err)
|
299 | t.strictEqual(response.statusCode, 413)
|
300 | })
|
301 | }
|
302 |
|
303 | sget({
|
304 | method: upMethod,
|
305 | url: `http://localhost:${fastify.server.address().port}/with-limit`,
|
306 | headers: { 'Content-Type': 'application/json' },
|
307 | body: {},
|
308 | json: true
|
309 | }, (err, response, body) => {
|
310 | t.error(err)
|
311 | t.strictEqual(response.statusCode, 413)
|
312 | })
|
313 | })
|
314 |
|
315 | test(`${upMethod} should fail with empty body and application/json content-type`, t => {
|
316 | if (upMethod === 'OPTIONS') return t.end()
|
317 |
|
318 | t.plan(12)
|
319 |
|
320 | fastify.inject({
|
321 | method: `${upMethod}`,
|
322 | url: '/',
|
323 | headers: {
|
324 | 'Content-Type': 'application/json'
|
325 | }
|
326 | }, (err, res) => {
|
327 | t.error(err)
|
328 | t.strictDeepEqual(JSON.parse(res.payload), {
|
329 | error: 'Bad Request',
|
330 | code: 'FST_ERR_CTP_EMPTY_JSON_BODY',
|
331 | message: "FST_ERR_CTP_EMPTY_JSON_BODY: Body cannot be empty when content-type is set to 'application/json'",
|
332 | statusCode: 400
|
333 | })
|
334 | })
|
335 |
|
336 | sget({
|
337 | method: upMethod,
|
338 | url: `http://localhost:${fastify.server.address().port}`,
|
339 | headers: {
|
340 | 'Content-Type': 'application/json'
|
341 | }
|
342 | }, (err, res, body) => {
|
343 | t.error(err)
|
344 | t.strictDeepEqual(JSON.parse(body.toString()), {
|
345 | error: 'Bad Request',
|
346 | code: 'FST_ERR_CTP_EMPTY_JSON_BODY',
|
347 | message: "FST_ERR_CTP_EMPTY_JSON_BODY: Body cannot be empty when content-type is set to 'application/json'",
|
348 | statusCode: 400
|
349 | })
|
350 | })
|
351 |
|
352 | fastify.inject({
|
353 | method: `${upMethod}`,
|
354 | url: '/',
|
355 | headers: {
|
356 | 'Content-Type': 'application/json'
|
357 | },
|
358 | payload: null
|
359 | }, (err, res) => {
|
360 | t.error(err)
|
361 | t.strictDeepEqual(JSON.parse(res.payload), {
|
362 | error: 'Bad Request',
|
363 | code: 'FST_ERR_CTP_EMPTY_JSON_BODY',
|
364 | message: "FST_ERR_CTP_EMPTY_JSON_BODY: Body cannot be empty when content-type is set to 'application/json'",
|
365 | statusCode: 400
|
366 | })
|
367 | })
|
368 |
|
369 | sget({
|
370 | method: upMethod,
|
371 | url: `http://localhost:${fastify.server.address().port}`,
|
372 | headers: {
|
373 | 'Content-Type': 'application/json'
|
374 | },
|
375 | payload: null
|
376 | }, (err, res, body) => {
|
377 | t.error(err)
|
378 | t.strictDeepEqual(JSON.parse(body.toString()), {
|
379 | error: 'Bad Request',
|
380 | code: 'FST_ERR_CTP_EMPTY_JSON_BODY',
|
381 | message: "FST_ERR_CTP_EMPTY_JSON_BODY: Body cannot be empty when content-type is set to 'application/json'",
|
382 | statusCode: 400
|
383 | })
|
384 | })
|
385 |
|
386 | fastify.inject({
|
387 | method: `${upMethod}`,
|
388 | url: '/',
|
389 | headers: {
|
390 | 'Content-Type': 'application/json'
|
391 | },
|
392 | payload: undefined
|
393 | }, (err, res) => {
|
394 | t.error(err)
|
395 | t.strictDeepEqual(JSON.parse(res.payload), {
|
396 | error: 'Bad Request',
|
397 | code: 'FST_ERR_CTP_EMPTY_JSON_BODY',
|
398 | message: "FST_ERR_CTP_EMPTY_JSON_BODY: Body cannot be empty when content-type is set to 'application/json'",
|
399 | statusCode: 400
|
400 | })
|
401 | })
|
402 |
|
403 | sget({
|
404 | method: upMethod,
|
405 | url: `http://localhost:${fastify.server.address().port}`,
|
406 | headers: {
|
407 | 'Content-Type': 'application/json'
|
408 | },
|
409 | payload: undefined
|
410 | }, (err, res, body) => {
|
411 | t.error(err)
|
412 | t.strictDeepEqual(JSON.parse(body.toString()), {
|
413 | error: 'Bad Request',
|
414 | code: 'FST_ERR_CTP_EMPTY_JSON_BODY',
|
415 | message: "FST_ERR_CTP_EMPTY_JSON_BODY: Body cannot be empty when content-type is set to 'application/json'",
|
416 | statusCode: 400
|
417 | })
|
418 | })
|
419 | })
|
420 | })
|
421 | }
|