H3ravel Request Lifecycle
The request lifecycle in H3ravel is structured, modular, and highly extensible. Here’s how a request flows through the system from server startup to response dispatch.
App Bootstrap (src/server.ts & src/bootstrap/app.ts)
This is the entry point of the application.
new app().bootstrap();Within bootstrap():
const app = new Application(process.cwd());- Creates the core Application container instance (inherits from Container)
- Registers all configured service providers
- Boots each service provider
- Creates an h3App (the internal H3 handler instance)
- Sets up the Kernel, injects middleware (like LogRequests)
- Starts listening via
serve()on port 3000 (default) or your custom defined port
At this point, your app is ready to receive requests.
Application Container Initialization
Next the service container bindings are registered in the Application class constructor:
this.registerBaseBindings();This will bind the core services like:
Application: The application itselfpath.base: The application base pathload.paths: Mappings of all other application paths
Then loads .env variables using dotenv.
The container now holds environment and path info required by providers and the app itself.
Service Provider Registration and Booting
The lifecycle proceeds to load all internal and external service providers, sorts them based on priority or order, calls each provider’s register() method and then calls each provider’s boot() method (if present).
Services such as config, view (Edge), and HTTP are registered here.
H3 Integration and Kernel Setup
const kernel = new Kernel(
(event) =>
HttpContext.init({
app,
request: new Request(event, app),
response: new Response(event, app),
}),
[new LogRequests()]
);Each incoming H3Event is wrapped into a custom HttpContext exposing the following for subsequent use:
request: The H3ravelRequestclassresponse: The H3ravelResponseclassapp: The H3ravel service container
H3 hands the event off to Kernel.handle().
Kernel Handling
The Kernel.handle() method converts H3Event into the HttpContext, dynamically binds the view renderer (Edge) to the container:
const ctx = this.context(event);
app.bind('view', () => async (template, params) => {
const edge = app.make('edge');
return ctx.response.html(await edge.render(template, params));
});Next it executes all middleware in sequence, if the result is a plain object, the required JSON headers will be set automatically:
Middleware Execution
The runMiddleware() method runs all middleware classes in order.
Each middleware must implement the IMiddleware contract interface, if no middleware interrupts, the final handler (next) is invoked.
Controller or Final Handler
At this point, the final handler which could be a controller or a callback is executed and the response is finalized and sent to the client.
Lifecycle Summary
| Stage | Description |
|---|---|
| bootstrap() | Starts app, registers providers, sets up H3 |
| Application | Holds the container, manages paths & env |
| Service Providers | Register & boot services into the container |
| Kernel | Handles request context, runs middleware, final handler |
| HttpContext | Unified object for request/response/app |
| Middleware | Optional processors before final handler |
| View/Response | Response generated by controller or handler |