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;
39import org.eclipse.jetty.websocket.api.Callback;
40import org.eclipse.jetty.websocket.api.Session;
42import dev.rafex.ether.websocket.core.WebSocketCloseStatus;
43import dev.rafex.ether.websocket.core.WebSocketSession;
47 private final Session session;
48 private final String path;
49 private final Map<String, String> pathParams;
50 private final Map<String, List<String>> queryParams;
51 private final Map<String, List<String>> headers;
52 private final Map<String, Object> attributes =
new ConcurrentHashMap<>();
55 final Map<String, List<String>> queryParams,
final Map<String, List<String>> headers) {
56 this.session = Objects.requireNonNull(session,
"session");
57 this.path = Objects.requireNonNull(path,
"path");
58 this.pathParams = Map.copyOf(pathParams);
59 this.queryParams = copyMultiMap(queryParams);
60 this.headers = copyMultiMap(headers);
65 return Integer.toHexString(System.identityHashCode(session));
75 final var protocol = session.getUpgradeResponse() ==
null ? null : session.getUpgradeResponse().getAcceptedSubProtocol();
76 return protocol ==
null ?
"" : protocol;
81 return session.isOpen();
86 return pathParams.get(name);
91 final var values = queryParams.get(name);
92 if (values ==
null || values.isEmpty()) {
99 public List<String>
queryAll(
final String name) {
100 return queryParams.getOrDefault(name, List.of());
105 final var values = headers.get(name);
106 if (values ==
null || values.isEmpty()) {
109 return values.get(0);
114 return attributes.get(name);
118 public void attribute(
final String name,
final Object value) {
120 attributes.remove(name);
123 attributes.put(name, value);
142 public CompletionStage<Void>
sendText(
final String text) {
143 final var future =
new CompletableFuture<Void>();
144 session.sendText(text, callbackOf(future));
149 public CompletionStage<Void>
sendBinary(
final ByteBuffer data) {
150 final var future =
new CompletableFuture<Void>();
151 session.sendBinary(data ==
null ? ByteBuffer.allocate(0) : data.slice(), callbackOf(future));
156 public CompletionStage<Void>
close(
final WebSocketCloseStatus status) {
157 final var future =
new CompletableFuture<Void>();
158 final var closeStatus = status ==
null ? WebSocketCloseStatus.NORMAL : status;
159 session.close(closeStatus.code(), closeStatus.reason(), callbackOf(future));
163 private static Callback callbackOf(
final CompletableFuture<Void> future) {
164 return Callback.from(() -> future.complete(
null), future::completeExceptionally);
167 private static Map<String, List<String>> copyMultiMap(
final Map<String, List<String>> input) {
168 final var out =
new LinkedHashMap<String, List<String>>();
170 for (
final var entry : input.entrySet()) {
171 out.put(entry.getKey(), entry.getValue() ==
null ? List.of() : List.copyOf(entry.getValue()));
174 return Collections.unmodifiableMap(out);
List< String > queryAll(final String name)
CompletionStage< Void > sendBinary(final ByteBuffer data)
CompletionStage< Void > close(final WebSocketCloseStatus status)
CompletionStage< Void > sendText(final String text)
Map< String, String > pathParams()
Object attribute(final String name)
String pathParam(final String name)
Map< String, List< String > > queryParams()
JettyWebSocketSession(final Session session, final String path, final Map< String, String > pathParams, final Map< String, List< String > > queryParams, final Map< String, List< String > > headers)
String queryFirst(final String name)
void attribute(final String name, final Object value)
Map< String, List< String > > headers()
String headerFirst(final String name)