Request Lifecycle
Relevant source files
The following files were used as context for generating this wiki page:The request lifecycle in gr8hopper describes the entire process from an incoming HTTP request to the final response. The system is built on the Hono web framework and is designed to operate in two distinct environments: Cloudflare Workers for edge deployment and a standard Node.js server for VPS or container-based deployment. This dual-architecture influences how requests are handled, but the core logic for redirection and administration remains consistent.
The lifecycle clearly separates public-facing redirect requests, which are heavily optimized for performance and caching, from authenticated administrative requests, which provide a UI and API for managing the service's configuration. Understanding this flow is crucial for development, deployment, and troubleshooting.
Entry Points and Initialization
The application has two primary entry points, one for each deployment target. Both entry points set up the Hono application, but they differ in how they handle configuration and storage.
Sources: src/index.ts, src/server.ts
This diagram shows the two distinct entry points for Cloudflare Workers and Node.js, leading to a common routing decision point.
Cloudflare Workers (src/index.ts)
In the Cloudflare Workers environment, handlers and configuration are initialized lazily on the first request to a specific worker instance (a "cold start"). This is an optimization to minimize startup time.
- Storage: Uses
KVAdapterto interact with Cloudflare KV for storing routes and settings. - Configuration: Reads
ADMIN_USERNAME,ADMIN_PASSWORD,ADMIN_PATH, and optional Cloudflare API credentials from environment variables (wrangler secrets). - Initialization: The
app.all('/*', ...)middleware checks if handlers likeredirectHandlerandadminHandlerare already initialized. If not, it creates them and caches them in module-level variables for subsequent requests.
Sources: src/index.ts:16-22, src/index.ts:26-64
Node.js Server (src/server.ts)
The Node.js server, intended for VPS or Docker deployments, initializes everything at startup.
- Storage: Uses
JsonFileAdapterto store routes and settings in a local JSON file (e.g.,routes.json). - Configuration: Reads
PORT,CONFIG_FILE,ADMIN_PATH,ADMIN_USERNAME, andADMIN_PASSWORDfrom environment variables. It also includes a helper to load.dev.varsfor local development. - Initialization: Handlers and middleware are created and applied to the Hono app instance once when the server process starts.
Sources: src/server.ts:100-149
Routing and Middleware
Once initialized, the Hono application routes incoming requests based on the URL path. A primary distinction is made between administrative paths and public redirect paths.
Request Routing Logic
The routing logic, particularly in src/index.ts, acts as a gatekeeper, directing traffic to the appropriate handler.
This diagram illustrates how an incoming request is triaged into either the admin or public redirect flow based on its path.
Sources: src/index.ts:67-97, src/server.ts:142-152
Authentication Middleware
All administrative routes are protected by HTTP Basic Authentication.
- The
basicAuthmiddleware is applied to the admin path (e.g.,/adminand/admin/*). - It checks for the
Authorizationheader and validates the credentials against theADMIN_USERNAMEandADMIN_PASSWORDenvironment variables. - If authentication fails, it returns a
401 Unauthorizedresponse, prompting the browser for credentials.
The sequence diagram below shows the authentication process for an admin request.
Public Redirect Lifecycle
This is the core functionality of gr8hopper, designed for high performance. The logic is encapsulated within the redirectHandler.
Sources: src/handlers/redirect.ts
Redirect Processing Flow
The handler follows a specific order of operations to find a matching route.
This flowchart details the step-by-step logic for processing a public redirect request.
Sources: src/handlers/redirect.ts:281-344
Route Matching
- Query Parameter Match: The system first checks for a route identifier in the query string, defined by the
route_paramsetting (default:r). If?r=my-routeis present, it attempts to find a route with the IDmy-route. - Exact Path Match: If no query parameter is found, it treats the request path (e.g.,
/my-route) as the route ID and looks for an exact match. - Pattern Match: If no exact match is found, it compares the path against all configured pattern routes.
- Pattern routes are cached for 10 seconds to improve performance.
- They are sorted by specificity to ensure the most precise pattern matches first (e.g.,
shop/item/123matches beforeshop/**).
Sources: src/handlers/redirect.ts:284-344
Redirect Response Generation
Once an active route is matched, the buildRedirectResponse function constructs the final 301 Moved Permanently response.
- Parameter Substitution: Placeholders in the route's
template(e.g.,{id}) are replaced with values from the request's query parameters or path parameters captured by a pattern match. The{route}placeholder is automatically filled with the route's ID. - Query Passthrough: If the route's
passthroughflag istrue, any query parameters from the source URL (like UTM tags) that are not already part of the template are appended to the destination URL. - Protocol Enforcement: The
ensureProtocolfunction ensures the final URL has a valid protocol, prependinghttps://if it appears to be a domain name. It also blocks dangerous schemes likejavascript:. - Caching Headers: The response includes
Cache-ControlandCDN-Cache-Controlheaders to enable aggressive caching at the browser and CDN levels.
Sources: src/handlers/redirect.ts:182-237
Fallback Handling
If no active route is matched, the request is sent to the fallback_url defined in the global settings. Placeholders in the fallback URL are also substituted with query parameters from the original request. Fallback redirects are cached for a shorter duration (max 30 minutes) to allow newly created routes to become effective more quickly.
Sources: src/handlers/redirect.ts:355-397
Admin Request Lifecycle
Requests to the admin path (default /admin) are handled by the adminHandler after passing authentication.
Sources: src/handlers/admin.ts, src/admin-html.ts
Serving the Admin UI
A request to the base admin path (e.g., /admin or /admin/) serves the single-page admin interface.
- The HTML is generated by the
getAdminHtmlfunction, which embeds all necessary CSS and JavaScript. This makes the application self-contained and easy to deploy without separate static asset files. - The client-side JavaScript then makes API calls to the
/admin/*endpoints to fetch and manage data.
Sources: src/index.ts:79-81, src/server.ts:150-151, src/admin-html.ts
Admin API Endpoints
The adminHandler exposes a RESTful API for managing routes and settings. All endpoints are prefixed with the admin path.
The following sequence diagram shows the flow for creating a new route:
The table below summarizes the available API endpoints.
| Method | Endpoint | Description |
|---|---|---|
GET | /routes | Lists all redirect routes. |
GET | /routes/:id | Retrieves a single route by its ID. |
POST | /routes | Creates a new route. |
PATCH | /routes/:id | Updates an existing route (partial updates supported). |
DELETE | /routes/:id | Deletes a route. |
GET | /settings | Retrieves global settings. |
PUT | /settings | Updates global settings. |
GET | /export | Exports all routes and settings as a single JSON file. |
POST | /import | Imports a JSON file, replacing all existing routes and settings. |
GET | /purge-cache/status | Checks if Cloudflare cache purging is configured. |
POST | /purge-cache | Triggers a full cache purge on Cloudflare (if configured). |
Sources: src/handlers/admin.ts:70-366, README.md:213-225
Conclusion
The gr8hopper request lifecycle is a well-defined process optimized for its dual roles as a high-performance redirector and a configurable management service. It leverages lazy initialization and aggressive caching for public requests while providing a secure, authenticated API for administration. The clear separation between the redirect and admin handlers, combined with a flexible dual-entry-point architecture, makes the system both efficient and maintainable.