hapi icon indicating copy to clipboard operation
hapi copied to clipboard

Server crashes when a route handler times out and onPreResponse is set to return h.abandon

Open quepop opened this issue 2 years ago • 1 comments

Support plan

  • is this issue currently blocking your project? (yes/no): yes
  • is this issue affecting a production system? (yes/no): yes

Context

  • node version: 17.3.0
  • module version with issue: 20.2.1
  • last module version without issue:
  • environment (e.g. node, browser, native): node, postman
  • used with (e.g. hapi application, another framework, standalone, ...): redis
  • any other relevant information:

What are you trying to achieve or the steps to reproduce?

I added an async wait_for function to one of my route handlers so that it exceeds the timeout value of route.timeout.server (set on every route)

Body of the onPreResponse method (set on every route):

if(request.response.statusCode == 200) return h.continue
request.raw.res.destroy()
return h.abandon

The above method works as expected under any other conditions (that lead to request.response.statusCode not being equal to 200).

What was the result you got?

My app crashed and I received the following error (I manually replaced some paths with ***):

            this.response._close();
                          ^

TypeError: this.response._close is not a function
    at Request._setResponse (/home/***/node_modules/@hapi/hapi/lib/request.js:525:27)
    at exports.execute (/home/***/node_modules/@hapi/hapi/lib/handler.js:38:13)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Request._lifecycle (/home/***/node_modules/@hapi/hapi/lib/request.js:371:32)
    at async Request._execute (/home/***/node_modules/@hapi/hapi/lib/request.js:281:9)

What result did you expect?

I expected the route to be abandoned and the app to not crash.

quepop avatar Jan 01 '22 17:01 quepop

I managed to fix the issue temporarily by changing the body of the onPreResponse method to:

if(request.response.statusCode == 200) return h.continue
request.raw.res.destroy()
if(
	isNativeError(request.response) 		&& 
	request.response.stack 				&& 
	request.response.stack.includes("timeoutReply")
) return h.continue
return h.abandon

quepop avatar Feb 27 '22 21:02 quepop