Add comprehensive Javadoc documentation to server components, including annotations, request/response handling, routing, and WebSocket support.
This commit is contained in:
@@ -5,17 +5,38 @@ import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Immutable configuration for the WebSocket subsystem: frame and message size limits, idle
|
||||
* timeout, allowed origins, negotiated subprotocols, and compression. Instances are created
|
||||
* through the nested {@link Builder}.
|
||||
*
|
||||
* <p>The values configured here govern how {@code HttpRequestHandler} sets up the WebSocket
|
||||
* portion of the Netty pipeline during the upgrade handshake.</p>
|
||||
*/
|
||||
public final class WebSocketConfig {
|
||||
|
||||
/** Maximum size, in bytes, of a single WebSocket frame payload. */
|
||||
private final int maxFramePayloadLength;
|
||||
/** Maximum size, in bytes, of an aggregated (multi-frame) message. */
|
||||
private final int maxAggregatedMessageSize;
|
||||
/** Idle timeout after which an inactive connection is closed; {@code null} disables it. */
|
||||
private final Duration idleTimeout;
|
||||
/** Explicit set of allowed origins; ignored when {@link #allowAnyOrigin} is {@code true}. */
|
||||
private final Set<String> allowedOrigins;
|
||||
/** Whether connections from any origin are accepted. */
|
||||
private final boolean allowAnyOrigin;
|
||||
/** Subprotocols offered during negotiation. */
|
||||
private final Set<String> subprotocols;
|
||||
/** Whether per-message deflate compression is enabled. */
|
||||
private final boolean compression;
|
||||
/** Whether the protocol handler matches the path by prefix rather than exact equality. */
|
||||
private final boolean checkStartsWith;
|
||||
|
||||
/**
|
||||
* Builds an immutable configuration from a {@link Builder}, defensively copying its sets.
|
||||
*
|
||||
* @param b the builder carrying the configured values
|
||||
*/
|
||||
private WebSocketConfig(Builder b) {
|
||||
this.maxFramePayloadLength = b.maxFramePayloadLength;
|
||||
this.maxAggregatedMessageSize = b.maxAggregatedMessageSize;
|
||||
@@ -27,110 +48,226 @@ public final class WebSocketConfig {
|
||||
this.checkStartsWith = b.checkStartsWith;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a configuration with all default values.
|
||||
*
|
||||
* @return a default configuration
|
||||
*/
|
||||
public static WebSocketConfig defaults() {
|
||||
return builder().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new, empty {@link Builder}.
|
||||
*
|
||||
* @return a fresh builder
|
||||
*/
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether a WebSocket upgrade from the given origin is permitted.
|
||||
*
|
||||
* @param origin the request's {@code Origin} header, may be {@code null}
|
||||
* @return {@code true} if any origin is allowed, or if the origin is in the allow-list;
|
||||
* {@code false} for a {@code null} or disallowed origin
|
||||
*/
|
||||
public boolean isOriginAllowed(String origin) {
|
||||
if (allowAnyOrigin) return true;
|
||||
if (origin == null) return false;
|
||||
return allowedOrigins.contains(origin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum single-frame payload size in bytes
|
||||
*/
|
||||
public int maxFramePayloadLength() {
|
||||
return maxFramePayloadLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum aggregated message size in bytes
|
||||
*/
|
||||
public int maxAggregatedMessageSize() {
|
||||
return maxAggregatedMessageSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the idle timeout, or {@code null} if idle connections are never closed
|
||||
*/
|
||||
public Duration idleTimeout() {
|
||||
return idleTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if connections from any origin are accepted
|
||||
*/
|
||||
public boolean allowAnyOrigin() {
|
||||
return allowAnyOrigin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the immutable set of explicitly allowed origins
|
||||
*/
|
||||
public Set<String> allowedOrigins() {
|
||||
return allowedOrigins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured subprotocols as a comma-separated string suitable for Netty's
|
||||
* protocol config.
|
||||
*
|
||||
* @return the comma-separated subprotocol list, or {@code null} if none are configured
|
||||
*/
|
||||
public String subprotocolsCsv() {
|
||||
if (subprotocols.isEmpty()) return null;
|
||||
return String.join(",", subprotocols);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if per-message compression is enabled
|
||||
*/
|
||||
public boolean compression() {
|
||||
return compression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the WebSocket path is matched by prefix rather than exactly
|
||||
*/
|
||||
public boolean checkStartsWith() {
|
||||
return checkStartsWith;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fluent builder for {@link WebSocketConfig}, pre-populated with sensible defaults: 64 KiB
|
||||
* frames, 1 MiB aggregated messages, a 60-second idle timeout, no origin restriction
|
||||
* list, compression enabled, and exact path matching.
|
||||
*/
|
||||
public static final class Builder {
|
||||
/** Maximum single-frame payload size in bytes; defaults to 64 KiB. */
|
||||
private int maxFramePayloadLength = 65_536;
|
||||
/** Maximum aggregated message size in bytes; defaults to 1 MiB. */
|
||||
private int maxAggregatedMessageSize = 1_048_576;
|
||||
/** Idle timeout; defaults to 60 seconds. */
|
||||
private Duration idleTimeout = Duration.ofSeconds(60);
|
||||
/** Accumulated allowed origins (insertion-ordered). */
|
||||
private final Set<String> allowedOrigins = new LinkedHashSet<>();
|
||||
/** Whether any origin is allowed; defaults to {@code false}. */
|
||||
private boolean allowAnyOrigin = false;
|
||||
/** Accumulated subprotocols (insertion-ordered). */
|
||||
private final Set<String> subprotocols = new LinkedHashSet<>();
|
||||
/** Whether compression is enabled; defaults to {@code true}. */
|
||||
private boolean compression = true;
|
||||
/** Whether path matching uses a prefix check; defaults to {@code false}. */
|
||||
private boolean checkStartsWith = false;
|
||||
|
||||
/**
|
||||
* Sets the maximum single-frame payload size.
|
||||
*
|
||||
* @param bytes the limit in bytes; must be positive
|
||||
* @return this builder, for fluent chaining
|
||||
* @throws IllegalArgumentException if {@code bytes <= 0}
|
||||
*/
|
||||
public Builder maxFramePayloadLength(int bytes) {
|
||||
if (bytes <= 0) throw new IllegalArgumentException("maxFramePayloadLength must be > 0");
|
||||
this.maxFramePayloadLength = bytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum aggregated message size.
|
||||
*
|
||||
* @param bytes the limit in bytes; must be positive
|
||||
* @return this builder, for fluent chaining
|
||||
* @throws IllegalArgumentException if {@code bytes <= 0}
|
||||
*/
|
||||
public Builder maxAggregatedMessageSize(int bytes) {
|
||||
if (bytes <= 0) throw new IllegalArgumentException("maxAggregatedMessageSize must be > 0");
|
||||
this.maxAggregatedMessageSize = bytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the idle timeout after which inactive connections are closed.
|
||||
*
|
||||
* @param timeout the idle timeout
|
||||
* @return this builder, for fluent chaining
|
||||
*/
|
||||
public Builder idleTimeout(Duration timeout) {
|
||||
this.idleTimeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the idle timeout, so connections are never closed for inactivity.
|
||||
*
|
||||
* @return this builder, for fluent chaining
|
||||
*/
|
||||
public Builder noIdleTimeout() {
|
||||
this.idleTimeout = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds one or more origins to the allow-list.
|
||||
*
|
||||
* @param origins the origins to allow
|
||||
* @return this builder, for fluent chaining
|
||||
*/
|
||||
public Builder allowedOrigins(String... origins) {
|
||||
Collections.addAll(this.allowedOrigins, origins);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows WebSocket connections from any origin.
|
||||
*
|
||||
* @return this builder, for fluent chaining
|
||||
*/
|
||||
public Builder anyOrigin() {
|
||||
this.allowAnyOrigin = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds one or more subprotocols to offer during negotiation.
|
||||
*
|
||||
* @param protocols the subprotocol names
|
||||
* @return this builder, for fluent chaining
|
||||
*/
|
||||
public Builder subprotocols(String... protocols) {
|
||||
Collections.addAll(this.subprotocols, protocols);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables per-message compression.
|
||||
*
|
||||
* @param enabled {@code true} to enable compression
|
||||
* @return this builder, for fluent chaining
|
||||
*/
|
||||
public Builder compression(boolean enabled) {
|
||||
this.compression = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the WebSocket path is matched by prefix rather than exact equality.
|
||||
*
|
||||
* @param v {@code true} to match by prefix
|
||||
* @return this builder, for fluent chaining
|
||||
*/
|
||||
public Builder checkStartsWith(boolean v) {
|
||||
this.checkStartsWith = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the immutable {@link WebSocketConfig}.
|
||||
*
|
||||
* @return the configured instance
|
||||
*/
|
||||
public WebSocketConfig build() {
|
||||
return new WebSocketConfig(this);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user