1 | 'use strict'
|
2 |
|
3 | const { validate: validateSchema } = require('./validation')
|
4 | const { preValidationHookRunner, preHandlerHookRunner } = require('./hooks')
|
5 | const wrapThenable = require('./wrapThenable')
|
6 | const {
|
7 | kReplyIsError,
|
8 | kRouteContext
|
9 | } = require('./symbols')
|
10 |
|
11 | function handleRequest (err, request, reply) {
|
12 | if (reply.sent === true) return
|
13 | if (err != null) {
|
14 | reply[kReplyIsError] = true
|
15 | reply.send(err)
|
16 | return
|
17 | }
|
18 |
|
19 | const method = request.raw.method
|
20 | const headers = request.headers
|
21 | const context = request[kRouteContext]
|
22 |
|
23 | if (method === 'GET' || method === 'HEAD') {
|
24 | handler(request, reply)
|
25 | return
|
26 | }
|
27 |
|
28 | const contentType = headers['content-type']
|
29 |
|
30 | if (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'TRACE' || method === 'SEARCH' ||
|
31 | method === 'PROPFIND' || method === 'PROPPATCH' || method === 'LOCK' || method === 'REPORT' || method === 'MKCALENDAR') {
|
32 | if (contentType === undefined) {
|
33 | if (
|
34 | headers['transfer-encoding'] === undefined &&
|
35 | (headers['content-length'] === '0' || headers['content-length'] === undefined)
|
36 | ) {
|
37 | handler(request, reply)
|
38 | } else {
|
39 | context.contentTypeParser.run('', handler, request, reply)
|
40 | }
|
41 | } else {
|
42 | context.contentTypeParser.run(contentType, handler, request, reply)
|
43 | }
|
44 | return
|
45 | }
|
46 |
|
47 | if (method === 'OPTIONS' || method === 'DELETE') {
|
48 | if (
|
49 | contentType !== undefined &&
|
50 | (
|
51 | headers['transfer-encoding'] !== undefined ||
|
52 | headers['content-length'] !== undefined
|
53 | )
|
54 | ) {
|
55 | context.contentTypeParser.run(contentType, handler, request, reply)
|
56 | } else {
|
57 | handler(request, reply)
|
58 | }
|
59 | return
|
60 | }
|
61 |
|
62 |
|
63 | handler(request, reply)
|
64 | }
|
65 |
|
66 | function handler (request, reply) {
|
67 | try {
|
68 | if (request[kRouteContext].preValidation !== null) {
|
69 | preValidationHookRunner(
|
70 | request[kRouteContext].preValidation,
|
71 | request,
|
72 | reply,
|
73 | preValidationCallback
|
74 | )
|
75 | } else {
|
76 | preValidationCallback(null, request, reply)
|
77 | }
|
78 | } catch (err) {
|
79 | preValidationCallback(err, request, reply)
|
80 | }
|
81 | }
|
82 |
|
83 | function preValidationCallback (err, request, reply) {
|
84 | if (reply.sent === true) return
|
85 |
|
86 | if (err != null) {
|
87 | reply[kReplyIsError] = true
|
88 | reply.send(err)
|
89 | return
|
90 | }
|
91 |
|
92 | const validationErr = validateSchema(reply[kRouteContext], request)
|
93 | const isAsync = (validationErr && typeof validationErr.then === 'function') || false
|
94 |
|
95 | if (isAsync) {
|
96 | const cb = validationCompleted.bind(null, request, reply)
|
97 | validationErr.then(cb, cb)
|
98 | } else {
|
99 | validationCompleted(request, reply, validationErr)
|
100 | }
|
101 | }
|
102 |
|
103 | function validationCompleted (request, reply, validationErr) {
|
104 | if (validationErr) {
|
105 | if (reply[kRouteContext].attachValidation === false) {
|
106 | reply.send(validationErr)
|
107 | return
|
108 | }
|
109 |
|
110 | reply.request.validationError = validationErr
|
111 | }
|
112 |
|
113 |
|
114 | if (request[kRouteContext].preHandler !== null) {
|
115 | preHandlerHookRunner(
|
116 | request[kRouteContext].preHandler,
|
117 | request,
|
118 | reply,
|
119 | preHandlerCallback
|
120 | )
|
121 | } else {
|
122 | preHandlerCallback(null, request, reply)
|
123 | }
|
124 | }
|
125 |
|
126 | function preHandlerCallback (err, request, reply) {
|
127 | if (reply.sent) return
|
128 |
|
129 | if (err != null) {
|
130 | reply[kReplyIsError] = true
|
131 | reply.send(err)
|
132 | return
|
133 | }
|
134 |
|
135 | let result
|
136 |
|
137 | try {
|
138 | result = request[kRouteContext].handler(request, reply)
|
139 | } catch (err) {
|
140 | reply[kReplyIsError] = true
|
141 | reply.send(err)
|
142 | return
|
143 | }
|
144 |
|
145 | if (result !== undefined) {
|
146 | if (result !== null && typeof result.then === 'function') {
|
147 | wrapThenable(result, reply)
|
148 | } else {
|
149 | reply.send(result)
|
150 | }
|
151 | }
|
152 | }
|
153 |
|
154 | module.exports = handleRequest
|
155 | module.exports[Symbol.for('internals')] = { handler, preHandlerCallback }
|