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.protocol;
28
29 import java.time.Instant;
30
31 import org.apache.hc.client5.http.HttpRoute;
32 import org.apache.hc.client5.http.RouteInfo.LayerType;
33 import org.apache.hc.client5.http.RouteInfo.TunnelType;
34 import org.apache.hc.client5.http.config.RequestConfig;
35 import org.apache.hc.client5.http.cookie.BasicCookieStore;
36 import org.apache.hc.client5.http.cookie.CookieOrigin;
37 import org.apache.hc.client5.http.cookie.CookieSpec;
38 import org.apache.hc.client5.http.cookie.CookieSpecFactory;
39 import org.apache.hc.client5.http.cookie.CookieStore;
40 import org.apache.hc.client5.http.cookie.StandardCookieSpec;
41 import org.apache.hc.client5.http.impl.cookie.BasicClientCookie;
42 import org.apache.hc.client5.http.impl.cookie.IgnoreCookieSpecFactory;
43 import org.apache.hc.client5.http.impl.cookie.RFC6265CookieSpecFactory;
44 import org.apache.hc.client5.http.impl.cookie.RFC6265StrictSpec;
45 import org.apache.hc.core5.http.Header;
46 import org.apache.hc.core5.http.HttpHost;
47 import org.apache.hc.core5.http.HttpRequest;
48 import org.apache.hc.core5.http.HttpRequestInterceptor;
49 import org.apache.hc.core5.http.config.Lookup;
50 import org.apache.hc.core5.http.config.RegistryBuilder;
51 import org.apache.hc.core5.http.message.BasicHttpRequest;
52 import org.junit.jupiter.api.Assertions;
53 import org.junit.jupiter.api.BeforeEach;
54 import org.junit.jupiter.api.Test;
55 import org.mockito.ArgumentMatchers;
56 import org.mockito.Mockito;
57
58 class TestRequestAddCookies {
59
60 private HttpHost target;
61 private CookieStore cookieStore;
62 private Lookup<CookieSpecFactory> cookieSpecRegistry;
63
64 @BeforeEach
65 void setUp() {
66 this.target = new HttpHost("localhost.local", 80);
67 this.cookieStore = new BasicCookieStore();
68 final BasicClientCookie cookie1 = new BasicClientCookie("name1", "value1");
69 cookie1.setDomain("localhost.local");
70 cookie1.setPath("/");
71 this.cookieStore.addCookie(cookie1);
72 final BasicClientCookie cookie2 = new BasicClientCookie("name2", "value2");
73 cookie2.setDomain("localhost.local");
74 cookie2.setPath("/");
75 this.cookieStore.addCookie(cookie2);
76
77 this.cookieSpecRegistry = RegistryBuilder.<CookieSpecFactory>create()
78 .register(StandardCookieSpec.RELAXED, new RFC6265CookieSpecFactory(
79 RFC6265CookieSpecFactory.CompatibilityLevel.RELAXED, null))
80 .register(StandardCookieSpec.STRICT, new RFC6265CookieSpecFactory(
81 RFC6265CookieSpecFactory.CompatibilityLevel.STRICT, null))
82 .register(StandardCookieSpec.IGNORE, new IgnoreCookieSpecFactory())
83 .build();
84 }
85
86 @Test
87 void testRequestParameterCheck() {
88 final HttpClientContext context = HttpClientContext.create();
89 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
90 Assertions.assertThrows(NullPointerException.class, () ->
91 interceptor.process(null, null, context));
92 }
93
94 @Test
95 void testContextParameterCheck() {
96 final HttpRequest request = new BasicHttpRequest("GET", "/");
97 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
98 Assertions.assertThrows(NullPointerException.class, () ->
99 interceptor.process(request, null, null));
100 }
101
102 @Test
103 void testAddCookies() throws Exception {
104 final HttpRequest request = new BasicHttpRequest("GET", "/");
105
106 final HttpRoute route = new HttpRoute(this.target, null, false);
107
108 final HttpClientContext context = HttpClientContext.create();
109 context.setRoute(route);
110 context.setCookieStore(this.cookieStore);
111 context.setCookieSpecRegistry(this.cookieSpecRegistry);
112
113 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
114 interceptor.process(request, null, context);
115
116 final Header[] headers = request.getHeaders("Cookie");
117 Assertions.assertNotNull(headers);
118 Assertions.assertEquals(1, headers.length);
119 Assertions.assertEquals("name1=value1; name2=value2", headers[0].getValue());
120
121 final CookieOrigin cookieOrigin = context.getCookieOrigin();
122 Assertions.assertNotNull(cookieOrigin);
123 Assertions.assertEquals(this.target.getHostName(), cookieOrigin.getHost());
124 Assertions.assertEquals(this.target.getPort(), cookieOrigin.getPort());
125 Assertions.assertEquals("/", cookieOrigin.getPath());
126 Assertions.assertFalse(cookieOrigin.isSecure());
127 }
128
129 @Test
130 void testCookiesForConnectRequest() throws Exception {
131 final HttpRequest request = new BasicHttpRequest("CONNECT", "www.somedomain.com");
132
133 final HttpRoute route = new HttpRoute(this.target, null, false);
134
135 final HttpClientContext context = HttpClientContext.create();
136 context.setRoute(route);
137 context.setCookieStore(this.cookieStore);
138 context.setCookieSpecRegistry(this.cookieSpecRegistry);
139
140 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
141 interceptor.process(request, null, context);
142
143 final Header[] headers = request.getHeaders("Cookie");
144 Assertions.assertNotNull(headers);
145 Assertions.assertEquals(0, headers.length);
146 }
147
148 @Test
149 void testNoCookieStore() throws Exception {
150 final HttpRequest request = new BasicHttpRequest("GET", "/");
151
152 final HttpRoute route = new HttpRoute(this.target, null, false);
153
154 final HttpClientContext context = HttpClientContext.create();
155 context.setRoute(route);
156 context.setCookieStore(null);
157 context.setCookieSpecRegistry(this.cookieSpecRegistry);
158
159 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
160 interceptor.process(request, null, context);
161
162 final Header[] headers = request.getHeaders("Cookie");
163 Assertions.assertNotNull(headers);
164 Assertions.assertEquals(0, headers.length);
165 }
166
167 @Test
168 void testNoCookieSpecRegistry() throws Exception {
169 final HttpRequest request = new BasicHttpRequest("GET", "/");
170
171 final HttpRoute route = new HttpRoute(this.target, null, false);
172
173 final HttpClientContext context = HttpClientContext.create();
174 context.setRoute(route);
175 context.setCookieStore(this.cookieStore);
176 context.setCookieSpecRegistry(null);
177
178 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
179 interceptor.process(request, null, context);
180
181 final Header[] headers = request.getHeaders("Cookie");
182 Assertions.assertNotNull(headers);
183 Assertions.assertEquals(0, headers.length);
184 }
185
186 @Test
187 void testNoHttpConnection() throws Exception {
188 final HttpRequest request = new BasicHttpRequest("GET", "/");
189
190 final HttpClientContext context = HttpClientContext.create();
191 context.setEndpointDetails(null);
192 context.setCookieStore(this.cookieStore);
193 context.setCookieSpecRegistry(this.cookieSpecRegistry);
194
195 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
196 interceptor.process(request, null, context);
197
198 final Header[] headers = request.getHeaders("Cookie");
199 Assertions.assertNotNull(headers);
200 Assertions.assertEquals(0, headers.length);
201 }
202
203 @Test
204 void testAddCookiesUsingExplicitCookieSpec() throws Exception {
205 final HttpRequest request = new BasicHttpRequest("GET", "/");
206 final RequestConfig config = RequestConfig.custom()
207 .setCookieSpec(StandardCookieSpec.STRICT)
208 .build();
209 final HttpRoute route = new HttpRoute(this.target, null, false);
210
211 final HttpClientContext context = HttpClientContext.create();
212 context.setRoute(route);
213 context.setRequestConfig(config);
214 context.setCookieStore(this.cookieStore);
215 context.setCookieSpecRegistry(this.cookieSpecRegistry);
216
217 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
218 interceptor.process(request, null, context);
219
220 final CookieSpec cookieSpec = context.getCookieSpec();
221 Assertions.assertTrue(cookieSpec instanceof RFC6265StrictSpec);
222
223 final Header[] headers1 = request.getHeaders("Cookie");
224 Assertions.assertNotNull(headers1);
225 Assertions.assertEquals(1, headers1.length);
226 Assertions.assertEquals("name1=value1; name2=value2", headers1[0].getValue());
227 }
228
229 @Test
230 void testAuthScopeInvalidRequestURI() throws Exception {
231 final HttpRequest request = new BasicHttpRequest("GET", "crap:");
232
233 final HttpRoute route = new HttpRoute(this.target, null, false);
234
235 final HttpClientContext context = HttpClientContext.create();
236 context.setRoute(route);
237 context.setCookieStore(this.cookieStore);
238 context.setCookieSpecRegistry(this.cookieSpecRegistry);
239
240 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
241 interceptor.process(request, null, context);
242 }
243
244 @Test
245 void testAuthScopeRemotePortWhenDirect() throws Exception {
246 final HttpRequest request = new BasicHttpRequest("GET", "/stuff");
247
248 this.target = new HttpHost("localhost.local");
249 final HttpRoute route = new HttpRoute(new HttpHost("localhost.local", 1234), null, false);
250
251 final HttpClientContext context = HttpClientContext.create();
252 context.setRoute(route);
253 context.setCookieStore(this.cookieStore);
254 context.setCookieSpecRegistry(this.cookieSpecRegistry);
255
256 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
257 interceptor.process(request, null, context);
258
259 final CookieOrigin cookieOrigin = context.getCookieOrigin();
260 Assertions.assertNotNull(cookieOrigin);
261 Assertions.assertEquals(this.target.getHostName(), cookieOrigin.getHost());
262 Assertions.assertEquals(1234, cookieOrigin.getPort());
263 Assertions.assertEquals("/stuff", cookieOrigin.getPath());
264 Assertions.assertFalse(cookieOrigin.isSecure());
265 }
266
267 @Test
268 void testAuthDefaultHttpPortWhenProxy() throws Exception {
269 final HttpRequest request = new BasicHttpRequest("GET", "/stuff");
270
271 this.target = new HttpHost("localhost.local");
272 final HttpRoute route = new HttpRoute(
273 new HttpHost("localhost.local", 80), null, new HttpHost("localhost", 8888), false);
274
275 final HttpClientContext context = HttpClientContext.create();
276 context.setRoute(route);
277 context.setCookieStore(this.cookieStore);
278 context.setCookieSpecRegistry(this.cookieSpecRegistry);
279
280 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
281 interceptor.process(request, null, context);
282
283 final CookieOrigin cookieOrigin = context.getCookieOrigin();
284 Assertions.assertNotNull(cookieOrigin);
285 Assertions.assertEquals(this.target.getHostName(), cookieOrigin.getHost());
286 Assertions.assertEquals(80, cookieOrigin.getPort());
287 Assertions.assertEquals("/stuff", cookieOrigin.getPath());
288 Assertions.assertFalse(cookieOrigin.isSecure());
289 }
290
291 @Test
292 void testAuthDefaultHttpsPortWhenProxy() throws Exception {
293 final HttpRequest request = new BasicHttpRequest("GET", "/stuff");
294
295 this.target = new HttpHost("https", "localhost", -1);
296 final HttpRoute route = new HttpRoute(
297 new HttpHost("https", "localhost", 443), null,
298 new HttpHost("http", "localhost", 8888), true, TunnelType.TUNNELLED, LayerType.LAYERED);
299
300 final HttpClientContext context = HttpClientContext.create();
301 context.setRoute(route);
302 context.setCookieStore(this.cookieStore);
303 context.setCookieSpecRegistry(this.cookieSpecRegistry);
304
305 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
306 interceptor.process(request, null, context);
307
308 final CookieOrigin cookieOrigin = context.getCookieOrigin();
309 Assertions.assertNotNull(cookieOrigin);
310 Assertions.assertEquals(this.target.getHostName(), cookieOrigin.getHost());
311 Assertions.assertEquals(443, cookieOrigin.getPort());
312 Assertions.assertEquals("/stuff", cookieOrigin.getPath());
313 Assertions.assertTrue(cookieOrigin.isSecure());
314 }
315
316 @Test
317 void testExcludeExpiredCookies() throws Exception {
318 final HttpRequest request = new BasicHttpRequest("GET", "/");
319
320 final BasicClientCookie cookie3 = new BasicClientCookie("name3", "value3");
321 cookie3.setDomain("localhost.local");
322 cookie3.setPath("/");
323 cookie3.setExpiryDate(Instant.now().plusMillis(100));
324 this.cookieStore.addCookie(cookie3);
325
326 Assertions.assertEquals(3, this.cookieStore.getCookies().size());
327
328 this.cookieStore = Mockito.spy(this.cookieStore);
329
330 final HttpRoute route = new HttpRoute(this.target, null, false);
331
332 final HttpClientContext context = HttpClientContext.create();
333 context.setRoute(route);
334 context.setCookieStore(this.cookieStore);
335 context.setCookieSpecRegistry(this.cookieSpecRegistry);
336
337
338 Thread.sleep(200);
339
340 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
341 interceptor.process(request, null, context);
342
343 final Header[] headers = request.getHeaders("Cookie");
344 Assertions.assertNotNull(headers);
345 Assertions.assertEquals(1, headers.length);
346 Assertions.assertEquals("name1=value1; name2=value2", headers[0].getValue());
347
348 Mockito.verify(this.cookieStore, Mockito.times(1)).clearExpired(ArgumentMatchers.any(Instant.class));
349 }
350
351 @Test
352 void testNoMatchingCookies() throws Exception {
353 final HttpRequest request = new BasicHttpRequest("GET", "/");
354
355 this.cookieStore.clear();
356 final BasicClientCookie cookie3 = new BasicClientCookie("name3", "value3");
357 cookie3.setDomain("www.somedomain.com");
358 cookie3.setPath("/");
359 this.cookieStore.addCookie(cookie3);
360
361 final HttpRoute route = new HttpRoute(this.target, null, false);
362
363 final HttpClientContext context = HttpClientContext.create();
364 context.setRoute(route);
365 context.setCookieStore(this.cookieStore);
366 context.setCookieSpecRegistry(this.cookieSpecRegistry);
367
368 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
369 interceptor.process(request, null, context);
370
371 final Header[] headers = request.getHeaders("Cookie");
372 Assertions.assertNotNull(headers);
373 Assertions.assertEquals(0, headers.length);
374 }
375
376
377 private BasicClientCookie makeCookie(final String name, final String value, final String domain, final String path) {
378 final BasicClientCookie cookie = new BasicClientCookie(name, value);
379 cookie.setDomain(domain);
380 cookie.setPath(path);
381 return cookie;
382 }
383
384 @Test
385
386 void testCookieOrder() throws Exception {
387 final HttpRequest request = new BasicHttpRequest("GET", "/foobar/yada/yada");
388
389 this.cookieStore.clear();
390
391 cookieStore.addCookie(makeCookie("nomatch", "value", "localhost.local", "/noway"));
392 cookieStore.addCookie(makeCookie("name2", "value", "localhost.local", "/foobar/yada"));
393 cookieStore.addCookie(makeCookie("name3", "value", "localhost.local", "/foobar"));
394 cookieStore.addCookie(makeCookie("name1", "value", "localhost.local", "/foobar/yada/yada"));
395
396 final HttpRoute route = new HttpRoute(this.target, null, false);
397
398 final HttpClientContext context = HttpClientContext.create();
399 context.setRoute(route);
400 context.setCookieStore(this.cookieStore);
401 context.setCookieSpecRegistry(this.cookieSpecRegistry);
402
403 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
404 interceptor.process(request, null, context);
405
406 final Header[] headers1 = request.getHeaders("Cookie");
407 Assertions.assertNotNull(headers1);
408 Assertions.assertEquals(1, headers1.length);
409
410 Assertions.assertEquals("name1=value; name2=value; name3=value", headers1[0].getValue());
411 }
412
413 @Test
414 void testSkipAddingCookiesWhenCookieHeaderPresent() throws Exception {
415
416 final HttpRequest request = new BasicHttpRequest("GET", "/");
417 request.addHeader("Cookie", "existingCookie=existingValue");
418
419 final HttpRoute route = new HttpRoute(this.target, null, false);
420
421 final HttpClientContext context = HttpClientContext.create();
422 context.setRoute(route);
423 context.setCookieStore(this.cookieStore);
424 context.setCookieSpecRegistry(this.cookieSpecRegistry);
425
426 final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE;
427 interceptor.process(request, null, context);
428
429
430 final Header[] headers = request.getHeaders("Cookie");
431 Assertions.assertNotNull(headers);
432 Assertions.assertEquals(1, headers.length);
433 Assertions.assertEquals("existingCookie=existingValue", headers[0].getValue());
434 }
435
436 }