Extension events are registered using the server.ext function. The first argument is the event name, and the second is the function to be executed for the event. The function takes "Request" and "Reply" arguments just like a route handler. To let the request continue though the lifecycle, I need to call reply.continue.
If "Continue" is not called, the request will get stuck and never respond to the client. If I call "Reply" instead, HAPI would respond to the client too soon.
To get an idea of when they are called during the request lifecycle, I'll register a function for each route extension event and log its name. I'm also logging when the route handler, itself, is called.
After making a request, you can see that the events are displayed one on each line of my terminal. "On request" executes as soon as "Request" is received, before it has passed through the router.
After the request has gone through the router, it needs to be authenticated. OnPreAuth runs before authentication, and onPostAuth runs after.
Validation is handled next. OnPreHandler runs, then, the route itself. OnPostHandler runs after the handler. Then, the response payload is validated on pre-response runs, and the response is sent to the client.
What are these extensions good for? Each extension can be used to manipulate the request or response at any point in the lifecycle. For example, in onRequest, I can force all requests to be interpreted as GETs to the route path.
To do so, I'll use request.seturl, pass in the string/, and pass the string GET to request.setmethod. Now, when I make a post request to /foo, it still hits my defined route.