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 package org.apache.hc.client5.http.impl;
28
29 import org.apache.hc.core5.http.HttpHeaders;
30 import org.apache.hc.core5.http.HttpResponse;
31 import org.apache.hc.core5.http.HttpStatus;
32 import org.apache.hc.core5.http.ProtocolException;
33 import org.apache.hc.core5.http.ProtocolVersion;
34 import org.apache.hc.core5.http.message.BasicHttpResponse;
35 import org.apache.hc.core5.http.ssl.TLS;
36 import org.junit.jupiter.api.Assertions;
37 import org.junit.jupiter.api.BeforeEach;
38 import org.junit.jupiter.api.Test;
39
40
41
42
43 class TestProtocolSwitchStrategy {
44
45 ProtocolSwitchStrategy switchStrategy;
46
47 @BeforeEach
48 void setUp() {
49 switchStrategy = new ProtocolSwitchStrategy();
50 }
51
52 @Test
53 void testSwitchToTLS() throws Exception {
54 final HttpResponse response1 = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
55 response1.addHeader(HttpHeaders.UPGRADE, "TLS");
56 Assertions.assertEquals(TLS.V_1_2.getVersion(), switchStrategy.switchProtocol(response1));
57
58 final HttpResponse response2 = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
59 response2.addHeader(HttpHeaders.UPGRADE, "TLS/1.3");
60 Assertions.assertEquals(TLS.V_1_3.getVersion(), switchStrategy.switchProtocol(response2));
61 }
62
63 @Test
64 void testSwitchToHTTP11AndTLS() throws Exception {
65 final HttpResponse response1 = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
66 response1.addHeader(HttpHeaders.UPGRADE, "TLS, HTTP/1.1");
67 Assertions.assertEquals(TLS.V_1_2.getVersion(), switchStrategy.switchProtocol(response1));
68
69 final HttpResponse response2 = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
70 response2.addHeader(HttpHeaders.UPGRADE, ",, HTTP/1.1, TLS, ");
71 Assertions.assertEquals(TLS.V_1_2.getVersion(), switchStrategy.switchProtocol(response2));
72
73 final HttpResponse response3 = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
74 response3.addHeader(HttpHeaders.UPGRADE, "HTTP/1.1");
75 response3.addHeader(HttpHeaders.UPGRADE, "TLS/1.2");
76 Assertions.assertEquals(TLS.V_1_2.getVersion(), switchStrategy.switchProtocol(response3));
77
78 final HttpResponse response4 = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
79 response4.addHeader(HttpHeaders.UPGRADE, "HTTP/1.1");
80 response4.addHeader(HttpHeaders.UPGRADE, "TLS/1.2, TLS/1.3");
81 Assertions.assertEquals(TLS.V_1_3.getVersion(), switchStrategy.switchProtocol(response4));
82 }
83
84 @Test
85 void testSwitchInvalid() {
86 final HttpResponse response1 = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
87 response1.addHeader(HttpHeaders.UPGRADE, "Crap");
88 Assertions.assertThrows(ProtocolException.class, () -> switchStrategy.switchProtocol(response1));
89
90 final HttpResponse response2 = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
91 response2.addHeader(HttpHeaders.UPGRADE, "TLS, huh?");
92 Assertions.assertThrows(ProtocolException.class, () -> switchStrategy.switchProtocol(response2));
93
94 final HttpResponse response3 = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
95 response3.addHeader(HttpHeaders.UPGRADE, ",,,");
96 Assertions.assertThrows(ProtocolException.class, () -> switchStrategy.switchProtocol(response3));
97 }
98
99 @Test
100 void testNullToken() throws ProtocolException {
101 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
102 response.addHeader(HttpHeaders.UPGRADE, "TLS,");
103 response.addHeader(HttpHeaders.UPGRADE, null);
104 Assertions.assertEquals(TLS.V_1_2.getVersion(), switchStrategy.switchProtocol(response));
105 }
106
107 @Test
108 void testWhitespaceOnlyToken() throws ProtocolException {
109 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
110 response.addHeader(HttpHeaders.UPGRADE, " , TLS");
111 Assertions.assertEquals(TLS.V_1_2.getVersion(), switchStrategy.switchProtocol(response));
112 }
113
114 @Test
115 void testUnsupportedTlsVersion() throws Exception {
116 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
117 response.addHeader(HttpHeaders.UPGRADE, "TLS/1.4");
118 Assertions.assertEquals(new ProtocolVersion("TLS", 1, 4), switchStrategy.switchProtocol(response));
119 }
120
121 @Test
122 void testUnsupportedTlsMajorVersion() throws Exception {
123 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
124 response.addHeader(HttpHeaders.UPGRADE, "TLS/2.0");
125 Assertions.assertEquals(new ProtocolVersion("TLS", 2, 0), switchStrategy.switchProtocol(response));
126 }
127
128 @Test
129 void testUnsupportedHttpVersion() {
130 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
131 response.addHeader(HttpHeaders.UPGRADE, "HTTP/2.0");
132 final ProtocolException ex = Assertions.assertThrows(ProtocolException.class, () ->
133 switchStrategy.switchProtocol(response));
134 Assertions.assertEquals("Unsupported protocol or HTTP version: HTTP/2.0", ex.getMessage());
135 }
136
137 @Test
138 void testInvalidTlsFormat() {
139 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
140 response.addHeader(HttpHeaders.UPGRADE, "TLS/abc");
141 final ProtocolException ex = Assertions.assertThrows(ProtocolException.class, () ->
142 switchStrategy.switchProtocol(response));
143 Assertions.assertEquals("Invalid TLS major version number; error at offset 7: <TLS/abc>", ex.getMessage());
144 }
145
146 @Test
147 void testHttp11Only() {
148 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
149 response.addHeader(HttpHeaders.UPGRADE, "HTTP/1.1");
150 final ProtocolException ex = Assertions.assertThrows(ProtocolException.class, () ->
151 switchStrategy.switchProtocol(response));
152 Assertions.assertEquals("Invalid protocol switch response: no TLS version found", ex.getMessage());
153 }
154
155 @Test
156 void testSwitchToTlsValid_TLS_1_2() throws Exception {
157 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
158 response.addHeader(HttpHeaders.UPGRADE, "TLS/1.2");
159 final ProtocolVersion result = switchStrategy.switchProtocol(response);
160 Assertions.assertEquals(TLS.V_1_2.getVersion(), result);
161 }
162
163 @Test
164 void testSwitchToTlsValid_TLS_1_0() throws Exception {
165 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
166 response.addHeader(HttpHeaders.UPGRADE, "TLS/1.0");
167 final ProtocolVersion result = switchStrategy.switchProtocol(response);
168 Assertions.assertEquals(TLS.V_1_0.getVersion(), result);
169 }
170
171 @Test
172 void testSwitchToTlsValid_TLS_1_1() throws Exception {
173 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
174 response.addHeader(HttpHeaders.UPGRADE, "TLS/1.1");
175 final ProtocolVersion result = switchStrategy.switchProtocol(response);
176 Assertions.assertEquals(TLS.V_1_1.getVersion(), result);
177 }
178
179 @Test
180 void testInvalidTlsFormat_NoSlash() {
181 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
182 response.addHeader(HttpHeaders.UPGRADE, "TLSv1");
183 final ProtocolException ex = Assertions.assertThrows(ProtocolException.class, () ->
184 switchStrategy.switchProtocol(response));
185 Assertions.assertEquals("Unsupported or invalid protocol: TLSv1", ex.getMessage());
186 }
187
188 @Test
189 void testSwitchToTlsValid_TLS_1() throws Exception {
190 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
191 response.addHeader(HttpHeaders.UPGRADE, "TLS/1");
192 final ProtocolVersion result = switchStrategy.switchProtocol(response);
193 Assertions.assertEquals(TLS.V_1_0.getVersion(), result);
194 }
195
196 @Test
197 void testInvalidTlsFormat_MissingMajor() {
198 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
199 response.addHeader(HttpHeaders.UPGRADE, "TLS/.1");
200 final ProtocolException ex = Assertions.assertThrows(ProtocolException.class, () ->
201 switchStrategy.switchProtocol(response));
202 Assertions.assertEquals("Invalid TLS major version number; error at offset 4: <TLS/.1>", ex.getMessage());
203 }
204
205 @Test
206 void testMultipleHttp11Tokens() {
207 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
208 response.addHeader(HttpHeaders.UPGRADE, "HTTP/1.1, HTTP/1.1");
209 final ProtocolException ex = Assertions.assertThrows(ProtocolException.class, () ->
210 switchStrategy.switchProtocol(response));
211 Assertions.assertEquals("Invalid protocol switch response: no TLS version found", ex.getMessage());
212 }
213
214 @Test
215 void testMixedInvalidAndValidTokens() {
216 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
217 response.addHeader(HttpHeaders.UPGRADE, "Crap, TLS/1.2, Invalid");
218 final ProtocolException ex = Assertions.assertThrows(ProtocolException.class, () ->
219 switchStrategy.switchProtocol(response));
220 Assertions.assertEquals("Unsupported or invalid protocol: Crap", ex.getMessage());
221 }
222
223 @Test
224 void testInvalidTlsFormat_NoProtocolName() {
225 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_SWITCHING_PROTOCOLS);
226 response.addHeader(HttpHeaders.UPGRADE, ",,/1.1");
227 final ProtocolException ex = Assertions.assertThrows(ProtocolException.class, () ->
228 switchStrategy.switchProtocol(response));
229 Assertions.assertEquals("Invalid protocol; error at offset 2: <,,/1.1>", ex.getMessage());
230 }
231
232 }