3.3 KiB
Request
The Request object is the immutable view of an incoming HTTP/1.1 request passed to every
handler. It is constructed by RequestParser, path/query parameters are injected once by the
router, and then it is handed to your handler unchanged.
server.get("/users/{id}", (req, res) -> { ... });
Method and path
HttpMethod method = req.method(); // GET, POST, PUT, …
String path = req.path(); // "/users/42" — decoded UTF-8, no query string
path() allocates a String by decoding the underlying ByteView. It is a convenience for
handlers that need the raw path; the router itself never calls it (it works on the ByteView
directly for zero-alloc routing).
Headers
String ct = req.header("Content-Type"); // first value, or null
List<String> accepts = req.headers("Accept"); // all values in order
List<String> all = req.headers(); // every header value
Lookup is case-insensitive: "content-type" and "Content-Type" resolve to the same header.
header() returns null if the header is absent. headers() returns an empty list.
Path parameters
Path parameters are declared in the route pattern with {name} syntax and injected by the
router before the handler runs.
server.get("/users/{id}/orders/{orderId}", (req, res) -> {
String id = req.param("id");
String orderId = req.param("orderId");
});
param() returns null if the route has no such parameter or is not parametric at all.
It never throws.
Query parameters
The query string is parsed lazily on the first query() or queries() call and cached for
the lifetime of the request.
// GET /search?q=flash&page=2&tag=java&tag=jvm
String q = req.query("q"); // "flash"
String page = req.query("page"); // "2"
List<String> tags = req.queries("tag"); // ["java", "jvm"]
String miss = req.query("absent"); // null
query() returns the first value for duplicate keys. queries() returns all values in
declaration order. Both return null / empty list for absent parameters, never throw.
Body
See BODY.md for a full reference. Quick summary:
// Small payloads — materialise into byte[]
byte[] json = req.body().bytes();
// Large payloads — stream without heap allocation
InputStream in = req.body().stream();
// Check size before choosing
long size = req.body().contentLength(); // -1 if Transfer-Encoding: chunked
The two modes are mutually exclusive per request. Calling stream() after bytes() returns
a ByteArrayInputStream over the cached array; calling bytes() after stream() has been
partially read produces undefined results.
Keep-alive and drain
After the response is fully written to the socket, the server calls req.drain() automatically
on keep-alive connections. This discards any unread body bytes so the socket is correctly
positioned for the next pipelined request. You never need to call this yourself.
Important: drain happens after the response write, not immediately after the handler returns. This matters for streaming responses that consume the request body on a separate thread (e.g. a pipe-fed echo): by the time drain runs, the body has already been consumed.