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