Handlers
The Handler interface
A handler is a @FunctionalInterface with a single method:
@FunctionalInterface
public interface Handler {
void handle(HTTPRequest req, HTTPResponse res) throws Exception;
}
That means handlers can be lambdas, method references, or full classes. The simplest possible one returns a status:
web.get("/health", (req, res) -> res.setStatus(200));
Handlers may throw any exception. Anything not caught by a downstream middleware (such as the ExceptionHandler) propagates out and the underlying HTTP server returns a 500.
Reading the request
HTTPRequest lives in org.lattejava.http. Useful methods:
getPath()andgetMethod()for routing decisionsgetHeader(name)andgetHeaders(name)for headersgetCookies()for incoming cookiesgetInputStream()for the raw body bytes (use aBodySupplierfor parsing)getAttribute(name)for path parameters and any data middleware has stashedgetBaseURL()forscheme://host:port(handy when building absolute URLs)
Path parameters declared with {name} syntax are exposed as request attributes:
web.get("/orders/{id}", (req, res) -> {
String id = (String) req.getAttribute("id");
// ...
});
Reading a header:
String acceptLang = req.getHeader("Accept-Language");
Writing the response
HTTPResponse provides:
setStatus(int)for the status codesetHeader(name, value)andsetContentType(String)for headersgetWriter()for text bodies (aPrintWriter)getOutputStream()for binary bodiessendRedirect(String)for 302 redirectsaddCookie(Cookie)forSet-Cookie
A handler that writes plain text:
web.get("/hello", (req, res) -> {
res.setStatus(200);
res.setContentType("text/plain; charset=utf-8");
res.getWriter().write("Hello, world!");
});
A handler that writes JSON manually (for richer JSON responses, see the Request Bodies page):
web.get("/api/health", (req, res) -> {
res.setStatus(200);
res.setContentType("application/json");
res.getWriter().write("{\"status\":\"ok\"}");
});
A redirect:
web.get("/old-path", (req, res) -> res.sendRedirect("/new-path"));
Reusing handlers as method references
Because Handler is a functional interface, any method with a matching signature can be used as a handler:
public class UsersController {
public void list(HTTPRequest req, HTTPResponse res) throws Exception {
res.getWriter().write("users");
}
public void show(HTTPRequest req, HTTPResponse res) throws Exception {
res.getWriter().write("user " + req.getAttribute("id"));
}
}
void main() {
var users = new UsersController();
new Web()
.get("/users", users::list)
.get("/users/{id}", users::show)
.start(8080);
}
This is a useful pattern when handlers need shared collaborators (a database connection, a service, etc.) — construct the controller once with its dependencies, then bind methods to routes.