Add WebSocket support with routing, origin validation, session management, and broadcasting
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
package dev.coph.nextusweb.server.websocket;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class WebSocketConfig {
|
||||
|
||||
private final int maxFramePayloadLength;
|
||||
private final int maxAggregatedMessageSize;
|
||||
private final Duration idleTimeout;
|
||||
private final Set<String> allowedOrigins;
|
||||
private final boolean allowAnyOrigin;
|
||||
private final Set<String> subprotocols;
|
||||
private final boolean compression;
|
||||
private final boolean checkStartsWith;
|
||||
|
||||
private WebSocketConfig(Builder b) {
|
||||
this.maxFramePayloadLength = b.maxFramePayloadLength;
|
||||
this.maxAggregatedMessageSize = b.maxAggregatedMessageSize;
|
||||
this.idleTimeout = b.idleTimeout;
|
||||
this.allowedOrigins = Set.copyOf(b.allowedOrigins);
|
||||
this.allowAnyOrigin = b.allowAnyOrigin;
|
||||
this.subprotocols = Set.copyOf(b.subprotocols);
|
||||
this.compression = b.compression;
|
||||
this.checkStartsWith = b.checkStartsWith;
|
||||
}
|
||||
|
||||
public static WebSocketConfig defaults() {
|
||||
return builder().build();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public boolean isOriginAllowed(String origin) {
|
||||
if (allowAnyOrigin) return true;
|
||||
if (origin == null) return false;
|
||||
return allowedOrigins.contains(origin);
|
||||
}
|
||||
|
||||
public int maxFramePayloadLength() {
|
||||
return maxFramePayloadLength;
|
||||
}
|
||||
|
||||
public int maxAggregatedMessageSize() {
|
||||
return maxAggregatedMessageSize;
|
||||
}
|
||||
|
||||
public Duration idleTimeout() {
|
||||
return idleTimeout;
|
||||
}
|
||||
|
||||
public boolean allowAnyOrigin() {
|
||||
return allowAnyOrigin;
|
||||
}
|
||||
|
||||
public Set<String> allowedOrigins() {
|
||||
return allowedOrigins;
|
||||
}
|
||||
|
||||
public String subprotocolsCsv() {
|
||||
if (subprotocols.isEmpty()) return null;
|
||||
return String.join(",", subprotocols);
|
||||
}
|
||||
|
||||
public boolean compression() {
|
||||
return compression;
|
||||
}
|
||||
|
||||
public boolean checkStartsWith() {
|
||||
return checkStartsWith;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private int maxFramePayloadLength = 65_536;
|
||||
private int maxAggregatedMessageSize = 1_048_576;
|
||||
private Duration idleTimeout = Duration.ofSeconds(60);
|
||||
private final Set<String> allowedOrigins = new LinkedHashSet<>();
|
||||
private boolean allowAnyOrigin = false;
|
||||
private final Set<String> subprotocols = new LinkedHashSet<>();
|
||||
private boolean compression = true;
|
||||
private boolean checkStartsWith = false;
|
||||
|
||||
public Builder maxFramePayloadLength(int bytes) {
|
||||
if (bytes <= 0) throw new IllegalArgumentException("maxFramePayloadLength must be > 0");
|
||||
this.maxFramePayloadLength = bytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder maxAggregatedMessageSize(int bytes) {
|
||||
if (bytes <= 0) throw new IllegalArgumentException("maxAggregatedMessageSize must be > 0");
|
||||
this.maxAggregatedMessageSize = bytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder idleTimeout(Duration timeout) {
|
||||
this.idleTimeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder noIdleTimeout() {
|
||||
this.idleTimeout = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder allowedOrigins(String... origins) {
|
||||
Collections.addAll(this.allowedOrigins, origins);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder anyOrigin() {
|
||||
this.allowAnyOrigin = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder subprotocols(String... protocols) {
|
||||
Collections.addAll(this.subprotocols, protocols);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder compression(boolean enabled) {
|
||||
this.compression = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder checkStartsWith(boolean v) {
|
||||
this.checkStartsWith = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WebSocketConfig build() {
|
||||
return new WebSocketConfig(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user