Add comprehensive Javadoc documentation to server components, including annotations, request/response handling, routing, and WebSocket support.
This commit is contained in:
@@ -9,22 +9,57 @@ import tools.jackson.databind.JsonNode;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A convenience wrapper around a Netty {@link FullHttpRequest} that exposes the parts of an
|
||||
* HTTP request handlers typically need: path parameters, query parameters, headers and the
|
||||
* request body (raw, as a parsed JSON tree, or deserialized into a type).
|
||||
*
|
||||
* <p>Query parameters and the parsed JSON body are computed lazily and cached, so repeated
|
||||
* accessors do not re-parse the request. A single {@code Request} instance is not intended to
|
||||
* be shared across threads.</p>
|
||||
*/
|
||||
public final class Request {
|
||||
|
||||
private final FullHttpRequest raw;
|
||||
private final Map<String, String> pathParams;
|
||||
private Map<String, List<String>> queryParams;
|
||||
private JsonNode jsonCache;
|
||||
|
||||
/** The underlying Netty request this wrapper delegates to. */
|
||||
private final FullHttpRequest raw;
|
||||
|
||||
/** Path parameters captured by the router while matching, keyed by name. */
|
||||
private final Map<String, String> pathParams;
|
||||
|
||||
/** Lazily decoded query-string parameters; {@code null} until first accessed. */
|
||||
private Map<String, List<String>> queryParams;
|
||||
|
||||
/** Lazily parsed JSON body; {@code null} until {@link #json()} is first called. */
|
||||
private JsonNode jsonCache;
|
||||
|
||||
/**
|
||||
* Creates a request wrapper.
|
||||
*
|
||||
* @param raw the underlying Netty request
|
||||
* @param pathParams the path parameters captured during routing, keyed by name
|
||||
*/
|
||||
public Request(FullHttpRequest raw, Map<String, String> pathParams) {
|
||||
this.raw = raw;
|
||||
this.pathParams = pathParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a path parameter captured during routing.
|
||||
*
|
||||
* @param name the parameter name as declared in the route (without braces)
|
||||
* @return the captured value, or {@code null} if no such parameter was matched
|
||||
*/
|
||||
public String pathParam(String name) {
|
||||
return pathParams.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first value of a query-string parameter, decoding the query string on first
|
||||
* access.
|
||||
*
|
||||
* @param name the query parameter name
|
||||
* @return the first value, or {@code null} if the parameter is absent or has no value
|
||||
*/
|
||||
public String queryParam(String name) {
|
||||
if (queryParams == null) {
|
||||
queryParams = new QueryStringDecoder(raw.uri()).parameters();
|
||||
@@ -33,6 +68,13 @@ public final class Request {
|
||||
return values == null || values.isEmpty() ? null : values.getFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all values of a query-string parameter, decoding the query string on first
|
||||
* access.
|
||||
*
|
||||
* @param name the query parameter name
|
||||
* @return the (possibly empty) list of values for the parameter; never {@code null}
|
||||
*/
|
||||
public List<String> queryParams(String name) {
|
||||
if (queryParams == null) {
|
||||
queryParams = new QueryStringDecoder(raw.uri()).parameters();
|
||||
@@ -40,14 +82,32 @@ public final class Request {
|
||||
return queryParams.getOrDefault(name, List.of());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a request header.
|
||||
*
|
||||
* @param name the (case-insensitive) header name
|
||||
* @return the header value, or {@code null} if not present
|
||||
*/
|
||||
public String header(String name) {
|
||||
return raw.headers().get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request body decoded as a UTF-8 string.
|
||||
*
|
||||
* @return the body as text (empty if there is no body)
|
||||
*/
|
||||
public String body() {
|
||||
return raw.content().toString(CharsetUtil.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the request body as a JSON tree, caching the result for subsequent calls. An
|
||||
* empty body resolves to a JSON {@code null} node rather than an error.
|
||||
*
|
||||
* @return the parsed JSON tree
|
||||
* @throws BadRequestException if the body is not valid JSON
|
||||
*/
|
||||
public JsonNode json() {
|
||||
if (jsonCache == null) {
|
||||
try {
|
||||
@@ -65,6 +125,17 @@ public final class Request {
|
||||
return jsonCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the request body directly into an instance of the given type.
|
||||
*
|
||||
* <p>Unlike {@link #json()}, the result is not cached and the body is read fresh on each
|
||||
* call.</p>
|
||||
*
|
||||
* @param type the target type to deserialize into
|
||||
* @param <T> the target type
|
||||
* @return the deserialized value
|
||||
* @throws BadRequestException if the body cannot be deserialized into {@code type}
|
||||
*/
|
||||
public <T> T jsonAs(Class<T> type) {
|
||||
try {
|
||||
byte[] bytes = new byte[raw.content().readableBytes()];
|
||||
@@ -76,11 +147,21 @@ public final class Request {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request's HTTP method.
|
||||
*
|
||||
* @return the HTTP method
|
||||
*/
|
||||
public HttpMethod method() {
|
||||
return raw.method();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request's path, with any query string stripped off.
|
||||
*
|
||||
* @return the decoded request path
|
||||
*/
|
||||
public String path() {
|
||||
return new QueryStringDecoder(raw.uri()).path();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user