1package dev.rafex.ether.websocket.jetty12;
29import java.nio.ByteBuffer;
30import java.util.Collections;
31import java.util.LinkedHashMap;
34import java.util.Objects;
35import java.util.concurrent.CompletableFuture;
36import java.util.concurrent.CompletionStage;
37import java.util.concurrent.ConcurrentHashMap;
38import java.util.concurrent.atomic.AtomicLong;
40import org.eclipse.jetty.websocket.api.Callback;
41import org.eclipse.jetty.websocket.api.Session;
43import dev.rafex.ether.websocket.core.WebSocketCloseStatus;
44import dev.rafex.ether.websocket.core.WebSocketSession;
56 private final Session session;
57 private final String path;
58 private final Map<String, String> pathParams;
59 private final Map<String, List<String>> queryParams;
60 private final Map<String, List<String>> headers;
61 private final Map<String, Object> attributes =
new ConcurrentHashMap<>();
62 private final String id;
64 private static final AtomicLong ID_COUNTER =
new AtomicLong(System.nanoTime());
77 final Map<String, List<String>> queryParams,
final Map<String, List<String>> headers) {
78 this.session = Objects.requireNonNull(session,
"session");
79 this.path = Objects.requireNonNull(path,
"path");
80 this.pathParams = Map.copyOf(pathParams);
81 this.queryParams = copyMultiMap(queryParams);
82 this.headers = copyMultiMap(headers);
83 this.id = Long.toHexString(ID_COUNTER.incrementAndGet());
114 final var protocol = session.getUpgradeResponse() ==
null ? null
115 : session.getUpgradeResponse().getAcceptedSubProtocol();
116 return protocol ==
null ?
"" : protocol;
126 return session.isOpen();
137 return pathParams.get(name);
148 final var values = queryParams.get(name);
149 if (values ==
null || values.isEmpty()) {
152 return values.get(0);
163 return queryParams.getOrDefault(name, List.of());
174 final var values = headers.get(name);
175 if (values ==
null || values.isEmpty()) {
178 return values.get(0);
189 return attributes.get(name);
201 public void attribute(
final String name,
final Object value) {
203 attributes.remove(name);
206 attributes.put(name, value);
246 public CompletionStage<Void>
sendText(
final String text) {
247 final var future =
new CompletableFuture<Void>();
248 session.sendText(text, callbackOf(future));
259 public CompletionStage<Void>
sendBinary(
final ByteBuffer data) {
260 final var future =
new CompletableFuture<Void>();
261 session.sendBinary(data ==
null ? ByteBuffer.allocate(0) : data.slice(), callbackOf(future));
272 public CompletionStage<Void>
close(
final WebSocketCloseStatus status) {
273 final var future =
new CompletableFuture<Void>();
274 final var closeStatus = status ==
null ? WebSocketCloseStatus.NORMAL : status;
275 session.close(closeStatus.code(), closeStatus.reason(), callbackOf(future));
285 private static Callback callbackOf(
final CompletableFuture<Void> future) {
286 return Callback.from(() -> future.complete(
null), future::completeExceptionally);
295 private static Map<String, List<String>> copyMultiMap(
final Map<String, List<String>> input) {
296 final var out =
new LinkedHashMap<String, List<String>>();
298 for (
final var entry : input.entrySet()) {
299 out.put(entry.getKey(), entry.getValue() ==
null ? List.of() : List.copyOf(entry.getValue()));
302 return Collections.unmodifiableMap(out);
List< String > queryAll(final String name)
Returns all values of a query parameter.
boolean isOpen()
Returns whether the underlying session is still open.
CompletionStage< Void > sendBinary(final ByteBuffer data)
Sends a binary message asynchronously.
CompletionStage< Void > close(final WebSocketCloseStatus status)
Closes the session with the given status code and reason.
CompletionStage< Void > sendText(final String text)
Sends a text message asynchronously.
Map< String, String > pathParams()
Returns an unmodifiable view of all path parameters.
Object attribute(final String name)
Returns a session-scoped attribute by name.
String path()
Returns the matched request path.
String subprotocol()
Returns the accepted subprotocol, or an empty string if none was negotiated.
String pathParam(final String name)
Returns the value of a single path parameter by name.
Map< String, List< String > > queryParams()
Returns an unmodifiable view of all query parameters.
JettyWebSocketSession(final Session session, final String path, final Map< String, String > pathParams, final Map< String, List< String > > queryParams, final Map< String, List< String > > headers)
Creates a session wrapper.
String queryFirst(final String name)
Returns the first value of a query parameter.
void attribute(final String name, final Object value)
Sets or removes a session-scoped attribute.
Map< String, List< String > > headers()
Returns an unmodifiable view of all HTTP headers.
String headerFirst(final String name)
Returns the first value of an HTTP header.
String id()
Returns a unique session identifier derived from the native session's identity hash code.
Representa una sesión WebSocket activa.