You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					147 lines
				
				3.3 KiB
			
		
		
			
		
	
	
					147 lines
				
				3.3 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | 
 | ||
|  | const { validate: validateSchema } = require('./validation') | ||
|  | const { hookRunner, hookIterator } = require('./hooks') | ||
|  | const wrapThenable = require('./wrapThenable') | ||
|  | 
 | ||
|  | const { kReplyIsError } = require('./symbols') | ||
|  | 
 | ||
|  | function handleRequest (err, request, reply) { | ||
|  |   if (reply.sent === true) return | ||
|  |   if (err != null) { | ||
|  |     reply.send(err) | ||
|  |     return | ||
|  |   } | ||
|  | 
 | ||
|  |   const method = request.raw.method | ||
|  |   const headers = request.headers | ||
|  | 
 | ||
|  |   if (method === 'GET' || method === 'HEAD') { | ||
|  |     handler(request, reply) | ||
|  |     return | ||
|  |   } | ||
|  | 
 | ||
|  |   const contentType = headers['content-type'] | ||
|  | 
 | ||
|  |   if (method === 'POST' || method === 'PUT' || method === 'PATCH') { | ||
|  |     if (contentType === undefined) { | ||
|  |       if ( | ||
|  |         headers['transfer-encoding'] === undefined && | ||
|  |         (headers['content-length'] === '0' || headers['content-length'] === undefined) | ||
|  |       ) { // Request has no body to parse
 | ||
|  |         handler(request, reply) | ||
|  |       } else { | ||
|  |         reply.context.contentTypeParser.run('', handler, request, reply) | ||
|  |       } | ||
|  |     } else { | ||
|  |       reply.context.contentTypeParser.run(contentType, handler, request, reply) | ||
|  |     } | ||
|  |     return | ||
|  |   } | ||
|  | 
 | ||
|  |   if (method === 'OPTIONS' || method === 'DELETE') { | ||
|  |     if ( | ||
|  |       contentType !== undefined && | ||
|  |       ( | ||
|  |         headers['transfer-encoding'] !== undefined || | ||
|  |         headers['content-length'] !== undefined | ||
|  |       ) | ||
|  |     ) { | ||
|  |       reply.context.contentTypeParser.run(contentType, handler, request, reply) | ||
|  |     } else { | ||
|  |       handler(request, reply) | ||
|  |     } | ||
|  |     return | ||
|  |   } | ||
|  | 
 | ||
|  |   // Return 404 instead of 405 see https://github.com/fastify/fastify/pull/862 for discussion
 | ||
|  |   reply.code(404).send(new Error('Not Found')) | ||
|  | } | ||
|  | 
 | ||
|  | function handler (request, reply) { | ||
|  |   try { | ||
|  |     if (reply.context.preValidation !== null) { | ||
|  |       hookRunner( | ||
|  |         reply.context.preValidation, | ||
|  |         hookIterator, | ||
|  |         request, | ||
|  |         reply, | ||
|  |         preValidationCallback | ||
|  |       ) | ||
|  |     } else { | ||
|  |       preValidationCallback(null, request, reply) | ||
|  |     } | ||
|  |   } catch (err) { | ||
|  |     preValidationCallback(err, request, reply) | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function preValidationCallback (err, request, reply) { | ||
|  |   if (reply.sent === true || | ||
|  |     reply.raw.writableEnded === true || | ||
|  |     reply.raw.writable === false) return | ||
|  | 
 | ||
|  |   if (err != null) { | ||
|  |     reply.send(err) | ||
|  |     return | ||
|  |   } | ||
|  | 
 | ||
|  |   const result = validateSchema(reply.context, request) | ||
|  |   if (result) { | ||
|  |     if (reply.context.attachValidation === false) { | ||
|  |       reply.code(400).send(result) | ||
|  |       return | ||
|  |     } | ||
|  | 
 | ||
|  |     reply.request.validationError = result | ||
|  |   } | ||
|  | 
 | ||
|  |   // preHandler hook
 | ||
|  |   if (reply.context.preHandler !== null) { | ||
|  |     hookRunner( | ||
|  |       reply.context.preHandler, | ||
|  |       hookIterator, | ||
|  |       request, | ||
|  |       reply, | ||
|  |       preHandlerCallback | ||
|  |     ) | ||
|  |   } else { | ||
|  |     preHandlerCallback(null, request, reply) | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function preHandlerCallback (err, request, reply) { | ||
|  |   if (reply.sent || | ||
|  |     reply.raw.writableEnded === true || | ||
|  |     reply.raw.writable === false) return | ||
|  | 
 | ||
|  |   if (err != null) { | ||
|  |     reply.send(err) | ||
|  |     return | ||
|  |   } | ||
|  | 
 | ||
|  |   let result | ||
|  | 
 | ||
|  |   try { | ||
|  |     result = reply.context.handler(request, reply) | ||
|  |   } catch (err) { | ||
|  |     if (!(err instanceof Error)) { | ||
|  |       reply[kReplyIsError] = true | ||
|  |     } | ||
|  | 
 | ||
|  |     reply.send(err) | ||
|  |     return | ||
|  |   } | ||
|  | 
 | ||
|  |   if (result !== undefined) { | ||
|  |     if (result !== null && typeof result.then === 'function') { | ||
|  |       wrapThenable(result, reply) | ||
|  |     } else { | ||
|  |       reply.send(result) | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = handleRequest | ||
|  | module.exports[Symbol.for('internals')] = { handler, preHandlerCallback } |