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 H3ravelRequest
classresponse
: The H3ravelResponse
classapp
: 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 |