/
Negotiated.java
154 lines (137 loc) · 4.49 KB
/
Negotiated.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//
// ========================================================================
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.websocket.core.internal;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.UrlEncoded;
import org.eclipse.jetty.websocket.core.ExtensionConfig;
import org.eclipse.jetty.websocket.core.WebSocketConstants;
public class Negotiated
{
private final URI requestURI;
private final Map<String, List<String>> parameterMap;
private final String subProtocol;
private final boolean secure;
private final ExtensionStack extensions;
private final String protocolVersion;
public Negotiated(URI requestURI, String subProtocol, boolean secure,
ExtensionStack extensions, String protocolVersion)
{
this.requestURI = toWebsocket(requestURI);
this.subProtocol = subProtocol;
this.secure = secure;
this.extensions = extensions;
this.protocolVersion = protocolVersion;
String rawQuery = requestURI.getRawQuery();
Map<String, List<String>> map;
if (StringUtil.isBlank(rawQuery))
{
map = Collections.emptyMap();
}
else
{
map = new HashMap<>();
MultiMap<String> params = new MultiMap<>();
UrlEncoded.decodeUtf8To(rawQuery, params);
for (String p : params.keySet())
{
map.put(p, Collections.unmodifiableList(params.getValues(p)));
}
}
this.parameterMap = Collections.unmodifiableMap(map);
}
public URI getRequestURI()
{
return requestURI;
}
public Map<String, List<String>> getParameterMap()
{
return parameterMap;
}
public String getSubProtocol()
{
return subProtocol;
}
public boolean isSecure()
{
return secure;
}
public ExtensionStack getExtensions()
{
return extensions;
}
public String getProtocolVersion()
{
return protocolVersion;
}
@Override
public String toString()
{
return String.format("[%s,%s,%b.%s]",
requestURI,
subProtocol,
secure,
extensions.getNegotiatedExtensions().stream().map(ExtensionConfig::getName).collect(Collectors.toList()));
}
public static Negotiated from(ExtensionStack extensions)
{
try
{
return new Negotiated(new URI("/"), "", false, extensions, WebSocketConstants.SPEC_VERSION_STRING);
}
catch (URISyntaxException e)
{
throw new RuntimeException(e);
}
}
/**
* Convert to WebSocket {@code ws} or {@code wss} scheme URIs
*
* <p>
* Converting {@code http} and {@code https} URIs to their WebSocket equivalent
*
* @param uri the input URI
* @return the WebSocket scheme URI for the input URI.
*/
public static URI toWebsocket(final URI uri)
{
try
{
Objects.requireNonNull(uri, "Input URI must not be null");
String httpScheme = uri.getScheme();
if (httpScheme == null)
return uri;
if (HttpScheme.WS.is(httpScheme) || HttpScheme.WSS.is(httpScheme))
return uri;
String afterScheme = uri.toString().substring(httpScheme.length());
if (HttpScheme.HTTP.is(httpScheme))
return new URI("ws" + afterScheme);
if (HttpScheme.HTTPS.is(httpScheme))
return new URI("wss" + afterScheme);
throw new URISyntaxException(uri.toString(), "Unrecognized HTTP scheme");
}
catch (URISyntaxException e)
{
throw new IllegalArgumentException(e);
}
}
}