@glorhythm/request
v1.0.0-beta
Published
Glorhythm library for request
Maintainers
Readme
@glorhythm/request
A small, typed HTTP request wrapper for Node.js IncomingMessage, built for the Glorhythm stack.
It provides:
- A simple
Requestclass that wraps Node'sIncomingMessage - Typed access to common HTTP headers
- Helpers for method, URL, query params, body, and IP detection
- JSON body parsing for non-GET/HEAD style methods
Installation
npm install @glorhythm/requestNote: This package is designed to be used inside the broader Glorhythm ecosystem where these packages are typically present.
Basic Usage
import http from "http";
import Request from "@glorhythm/request";
const server = http.createServer(async (rawReq, res) => {
const req = new Request(rawReq);
// Parse JSON body if applicable
await req.parseBody();
console.log("Method:", req.method());
console.log("URL:", req.url());
console.log("IP:", req.ip());
console.log("User-Agent:", req.header("user-agent"));
console.log("Query params:", Object.fromEntries(req.query));
console.log("Body params:", Object.fromEntries(req.body));
res.statusCode = 200;
res.end("OK");
});
server.listen(3000, () => {
console.log("Listening on http://localhost:3000");
});API
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE"
A narrow union of supported HTTP methods.
class Request
Constructor
new Request(raw: IncomingMessage);raw– Node.jsIncomingMessageinstance fromhttp.createServer,https.createServer, or compatible frameworks.
The constructor:
- Stores the raw request
- Immediately parses the query string from the URL into
req.query
Properties
query: Map<string, any>
A Map of query-string parameters parsed from the URL.
Example:
// /users?page=2&role=admin
req.query.get("page"); // "2"
req.query.get("role"); // "admin"body: Map<string, any>
A Map of parsed body parameters. Filled only after calling await req.parseBody().
Example (JSON):
// Body: { "email": "[email protected]", "password": "123456" }
await req.parseBody();
req.body.get("email"); // "[email protected]"
req.body.get("password"); // "123456"Methods
method(): HttpMethod
Returns the HTTP method, defaulting to "GET" if undefined:
const method = req.method(); // "GET", "POST", "PUT", "PATCH", or "DELETE"url(): string
Returns the raw URL string from the incoming request, defaulting to "/" if missing:
const url = req.url(); // e.g. "/users?page=2"header<K extends StrictHeaderKey>(key: K): StrictHeaderValue<K>
Typed header getter.
StrictHeaderKey– A union of known/whitelisted HTTP header names (all lowercase).StrictHeaderValue<K>– The corresponding type for that header (usuallystringorstring[]).
Example:
const userAgent = req.header("user-agent"); // string | undefined
const contentType = req.header("content-type"); // string | undefined
const accept = req.header("accept"); // string | undefinedSince the keys are constrained, TypeScript will catch typos in header names.
ip(): string
Returns the best guess IPv4 address for the client:
- Checks
x-forwarded-forheader, taking the first entry. - Falls back to
raw.socket.remoteAddress. - Strips the IPv6-mapped IPv4 prefix (
::ffff:). - Caches the result for subsequent calls.
Usage:
const ip = req.ip(); // e.g. "203.0.113.42"Note: For correct IP detection behind proxies/load balancers, ensure
x-forwarded-foris properly set by your infrastructure.
parseBody(): Promise<void>
Reads and parses the request body if the method is body-capable.
Method Filter
parseBody will skip parsing for:
GETHEADOPTIONSTRACECONNECT
Only methods like POST, PUT, PATCH, and DELETE are processed.
Parsing Rules
- Collects all incoming data chunks into a
Buffer. - If there is no content, it returns early.
- Inspects the
content-typeheader:- If empty or includes
"application/json", attempts to parse the body as JSON. - On successful JSON parse, flattens top-level keys into
req.bodyMap.
- If empty or includes
Example:
await req.parseBody();
if (req.method() === "POST") {
const payload = Object.fromEntries(req.body);
console.log("Received JSON:", payload);
}Important: If the body is not valid JSON for a JSON request,
JSON.parsewill throw. Handle this in your higher-level request handling by wrappingparseBodyintry/catch, or adjust the implementation to catch and handle the error.
Header Typings
The library defines a StrictIncomingHttpHeaders interface and the utility types:
type StrictHeaderKey = keyof StrictIncomingHttpHeaders;
type StrictHeaderValue<K extends StrictHeaderKey> =
StrictIncomingHttpHeaders[K];This gives you strict, auto-completed header names instead of arbitrary strings.
Example: Minimal Router
import http from "http";
import Request from "@glorhythm/request";
const server = http.createServer(async (rawReq, res) => {
const req = new Request(rawReq);
if (req.method() === "GET" && req.url().startsWith("/health")) {
res.statusCode = 200;
res.setHeader("content-type", "application/json");
return res.end(JSON.stringify({ status: "ok" }));
}
if (req.method() === "POST" && req.url() === "/echo") {
await req.parseBody();
const body = Object.fromEntries(req.body);
res.statusCode = 200;
res.setHeader("content-type", "application/json");
return res.end(JSON.stringify({ body, ip: req.ip() }));
}
res.statusCode = 404;
res.end("Not Found");
});
server.listen(3000, () => {
console.log("Listening on http://localhost:3000");
});TypeScript
The package ships with type definitions:
main:dist/index.jstypes:dist/index.d.tsexportsconfigured for ESM/CJS.
Typical TS usage:
import Request from "@glorhythm/request";
import { IncomingMessage } from "http";
function wrap(raw: IncomingMessage) {
const req = new Request(raw);
return req;
}License
MIT © Glorhythm
