View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.client5.http.impl.cookie;
29  
30  import java.util.Arrays;
31  import java.util.List;
32  
33  import org.apache.hc.client5.http.cookie.CommonCookieAttributeHandler;
34  import org.apache.hc.client5.http.cookie.Cookie;
35  import org.apache.hc.client5.http.cookie.CookieOrigin;
36  import org.apache.hc.client5.http.cookie.MalformedCookieException;
37  import org.apache.hc.client5.http.cookie.SetCookie;
38  import org.apache.hc.core5.http.Header;
39  import org.apache.hc.core5.http.message.BasicHeader;
40  import org.junit.Assert;
41  import org.junit.Test;
42  import org.mockito.ArgumentMatchers;
43  import org.mockito.Mockito;
44  
45  public class TestRFC6265CookieSpec {
46  
47      @Test
48      public void testParseCookieBasics() throws Exception {
49          final CommonCookieAttributeHandler h1 = Mockito.mock(CommonCookieAttributeHandler.class);
50          Mockito.when(h1.getAttributeName()).thenReturn("this");
51          final CommonCookieAttributeHandler h2 = Mockito.mock(CommonCookieAttributeHandler.class);
52          Mockito.when(h2.getAttributeName()).thenReturn("that");
53  
54          final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec(h1, h2);
55  
56          final Header header = new BasicHeader("Set-Cookie", "name = value ; this = stuff;");
57          final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
58          final List<Cookie> cookies = cookiespec.parse(header, origin);
59  
60          Assert.assertEquals(1, cookies.size());
61          final Cookie cookie = cookies.get(0);
62          Assert.assertEquals("name", cookie.getName());
63          Assert.assertEquals("value", cookie.getValue());
64          Assert.assertEquals("/path", cookie.getPath());
65          Assert.assertEquals("host", cookie.getDomain());
66          Assert.assertEquals("stuff", cookie.getAttribute("this"));
67          Assert.assertEquals(null, cookie.getAttribute("that"));
68  
69          Mockito.verify(h1).parse(ArgumentMatchers.<SetCookie>any(), ArgumentMatchers.eq("stuff"));
70          Mockito.verify(h2, Mockito.never()).parse(ArgumentMatchers.<SetCookie>any(), ArgumentMatchers.anyString());
71      }
72  
73      @Test
74      public void testParseCookieQuotedValue() throws Exception {
75          final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec();
76  
77          final Header header = new BasicHeader("Set-Cookie", "name = \" one, two, three; four \" ; this = stuff;");
78          final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
79          final List<Cookie> cookies = cookiespec.parse(header, origin);
80  
81          Assert.assertEquals(1, cookies.size());
82          final Cookie cookie = cookies.get(0);
83          Assert.assertEquals("name", cookie.getName());
84          Assert.assertEquals(" one, two, three; four ", cookie.getValue());
85          Assert.assertEquals("stuff", cookie.getAttribute("this"));
86      }
87  
88      @Test(expected = MalformedCookieException.class)
89      public void testParseCookieWrongHeader() throws Exception {
90          final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec();
91  
92          final Header header = new BasicHeader("Set-Cookie2", "blah");
93          final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
94          cookiespec.parse(header, origin);
95      }
96  
97      @Test
98      public void testParseCookieMissingName() throws Exception {
99          final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec();
100 
101         final Header header = new BasicHeader("Set-Cookie", "=blah ; this = stuff;");
102         final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
103         final List<Cookie> cookies = cookiespec.parse(header, origin);
104         Assert.assertEquals(0, cookies.size());
105     }
106 
107     @Test
108     public void testParseCookieMissingValue1() throws Exception {
109         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec();
110 
111         final Header header = new BasicHeader("Set-Cookie", "blah");
112         final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
113         final List<Cookie> cookies = cookiespec.parse(header, origin);
114         Assert.assertEquals(0, cookies.size());
115     }
116 
117     @Test(expected = MalformedCookieException.class)
118     public void testParseCookieMissingValue2() throws Exception {
119         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec();
120 
121         final Header header = new BasicHeader("Set-Cookie", "blah;");
122         final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
123         cookiespec.parse(header, origin);
124     }
125 
126     @Test
127     public void testParseCookieEmptyValue() throws Exception {
128         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec();
129 
130         final Header header = new BasicHeader("Set-Cookie", "blah=;");
131         final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
132         final List<Cookie> cookies = cookiespec.parse(header, origin);
133         Assert.assertEquals(1, cookies.size());
134         final Cookie cookie = cookies.get(0);
135         Assert.assertEquals("blah", cookie.getName());
136         Assert.assertEquals("", cookie.getValue());
137     }
138 
139     @Test
140     public void testParseCookieWithAttributes() throws Exception {
141         final CommonCookieAttributeHandler h1 = Mockito.mock(CommonCookieAttributeHandler.class);
142         Mockito.when(h1.getAttributeName()).thenReturn("this");
143         final CommonCookieAttributeHandler h2 = Mockito.mock(CommonCookieAttributeHandler.class);
144         Mockito.when(h2.getAttributeName()).thenReturn("that");
145 
146         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec(h1, h2);
147 
148         final Header header = new BasicHeader("Set-Cookie", "name = value ; p1 = v ; p2 = v,0; p3 ; p4");
149         final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
150         final List<Cookie> cookies = cookiespec.parse(header, origin);
151 
152         Assert.assertEquals(1, cookies.size());
153         final Cookie cookie = cookies.get(0);
154         Assert.assertEquals("name", cookie.getName());
155         Assert.assertEquals("value", cookie.getValue());
156         Assert.assertEquals("v", cookie.getAttribute("p1"));
157         Assert.assertEquals("v,0", cookie.getAttribute("p2"));
158         Assert.assertTrue(cookie.containsAttribute("p3"));
159         Assert.assertTrue(cookie.containsAttribute("p4"));
160         Assert.assertFalse(cookie.containsAttribute("p5"));
161     }
162 
163     @Test
164     public void testParseCookieWithAttributes2() throws Exception {
165         final CommonCookieAttributeHandler h1 = Mockito.mock(CommonCookieAttributeHandler.class);
166         Mockito.when(h1.getAttributeName()).thenReturn("this");
167         final CommonCookieAttributeHandler h2 = Mockito.mock(CommonCookieAttributeHandler.class);
168         Mockito.when(h2.getAttributeName()).thenReturn("that");
169 
170         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec(h1, h2);
171 
172         final Header header = new BasicHeader("Set-Cookie", "name = value ; p1 = v");
173         final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
174         final List<Cookie> cookies = cookiespec.parse(header, origin);
175 
176         Assert.assertEquals(1, cookies.size());
177         final Cookie cookie = cookies.get(0);
178         Assert.assertEquals("name", cookie.getName());
179         Assert.assertEquals("value", cookie.getValue());
180         Assert.assertEquals("v", cookie.getAttribute("p1"));
181     }
182 
183     @Test
184     public void testParseCookieWithAttributes3() throws Exception {
185         final CommonCookieAttributeHandler h1 = Mockito.mock(CommonCookieAttributeHandler.class);
186         Mockito.when(h1.getAttributeName()).thenReturn("this");
187         final CommonCookieAttributeHandler h2 = Mockito.mock(CommonCookieAttributeHandler.class);
188         Mockito.when(h2.getAttributeName()).thenReturn("that");
189 
190         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec(h1, h2);
191 
192         final Header header = new BasicHeader("Set-Cookie", "name = value ; p1 =");
193         final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
194         final List<Cookie> cookies = cookiespec.parse(header, origin);
195 
196         Assert.assertEquals(1, cookies.size());
197         final Cookie cookie = cookies.get(0);
198         Assert.assertEquals("name", cookie.getName());
199         Assert.assertEquals("value", cookie.getValue());
200         Assert.assertEquals("", cookie.getAttribute("p1"));
201     }
202 
203     @Test
204     public void testValidateCookieBasics() throws Exception {
205         final CommonCookieAttributeHandler h1 = Mockito.mock(CommonCookieAttributeHandler.class);
206         Mockito.when(h1.getAttributeName()).thenReturn("this");
207         final CommonCookieAttributeHandler h2 = Mockito.mock(CommonCookieAttributeHandler.class);
208         Mockito.when(h2.getAttributeName()).thenReturn("that");
209 
210         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec(h1, h2);
211 
212         final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
213         final BasicClientCookie cookie = new BasicClientCookie("name", "value");
214         cookiespec.validate(cookie, origin);
215 
216         Mockito.verify(h1).validate(cookie, origin);
217         Mockito.verify(h2).validate(cookie, origin);
218     }
219 
220     @Test
221     public void testMatchCookie() throws Exception {
222         final CommonCookieAttributeHandler h1 = Mockito.mock(CommonCookieAttributeHandler.class);
223         Mockito.when(h1.getAttributeName()).thenReturn("this");
224         final CommonCookieAttributeHandler h2 = Mockito.mock(CommonCookieAttributeHandler.class);
225         Mockito.when(h2.getAttributeName()).thenReturn("that");
226 
227         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec(h1, h2);
228 
229         final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
230         final BasicClientCookie cookie = new BasicClientCookie("name", "value");
231 
232         Mockito.when(h1.match(cookie, origin)).thenReturn(true);
233         Mockito.when(h2.match(cookie, origin)).thenReturn(true);
234 
235         Assert.assertTrue(cookiespec.match(cookie, origin));
236 
237         Mockito.verify(h1).match(cookie, origin);
238         Mockito.verify(h2).match(cookie, origin);
239     }
240 
241     @Test
242     public void testMatchCookieNoMatch() throws Exception {
243         final CommonCookieAttributeHandler h1 = Mockito.mock(CommonCookieAttributeHandler.class);
244         Mockito.when(h1.getAttributeName()).thenReturn("this");
245         final CommonCookieAttributeHandler h2 = Mockito.mock(CommonCookieAttributeHandler.class);
246         Mockito.when(h2.getAttributeName()).thenReturn("that");
247 
248         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec(h1, h2);
249 
250         final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
251         final BasicClientCookie cookie = new BasicClientCookie("name", "value");
252 
253         Mockito.when(h1.match(cookie, origin)).thenReturn(false);
254         Mockito.when(h2.match(cookie, origin)).thenReturn(false);
255 
256         Assert.assertFalse(cookiespec.match(cookie, origin));
257 
258         Mockito.verify(h1).match(cookie, origin);
259         Mockito.verify(h2, Mockito.never()).match(cookie, origin);
260     }
261 
262     @Test
263     public void testFormatCookiesBasics() throws Exception {
264         final Cookie cookie1 = new BasicClientCookie("name1", "value");
265 
266         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec();
267         final List<Header> headers = cookiespec.formatCookies(Arrays.asList(cookie1));
268         Assert.assertNotNull(headers);
269         Assert.assertEquals(1, headers.size());
270         final Header header = headers.get(0);
271         Assert.assertEquals("Cookie", header.getName());
272         Assert.assertEquals("name1=value", header.getValue());
273     }
274 
275     @Test
276     public void testFormatCookiesIllegalCharsInValue() throws Exception {
277         final Cookie cookie1 = new BasicClientCookie("name1", "value");
278         final Cookie cookie2 = new BasicClientCookie("name2", "some value");
279         final Cookie cookie3 = new BasicClientCookie("name3", "\"\\\"");
280         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec();
281         final List<Header> headers = cookiespec.formatCookies(Arrays.asList(cookie1, cookie2, cookie3));
282         Assert.assertNotNull(headers);
283         Assert.assertEquals(1, headers.size());
284         final Header header = headers.get(0);
285         Assert.assertEquals("Cookie", header.getName());
286         Assert.assertEquals("name1=value; name2=\"some value\"; name3=\"\\\"\\\\\\\"\"", header.getValue());
287     }
288 
289     @Test
290     public void testParseCookieMultipleAttributes() throws Exception {
291         final CommonCookieAttributeHandler h1 = Mockito.mock(CommonCookieAttributeHandler.class);
292         Mockito.when(h1.getAttributeName()).thenReturn("this");
293 
294         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec(h1);
295 
296         final Header header = new BasicHeader("Set-Cookie", "name = value ; this = stuff; this = morestuff;");
297         final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
298         cookiespec.parse(header, origin);
299 
300         Mockito.verify(h1).parse(ArgumentMatchers.<SetCookie>any(), ArgumentMatchers.eq("morestuff"));
301         Mockito.verify(h1, Mockito.times(1)).parse(ArgumentMatchers.<SetCookie>any(), ArgumentMatchers.anyString());
302     }
303 
304     @Test
305     public void testParseCookieMaxAgeOverExpires() throws Exception {
306         final CommonCookieAttributeHandler h1 = Mockito.mock(CommonCookieAttributeHandler.class);
307         Mockito.when(h1.getAttributeName()).thenReturn("Expires");
308         final CommonCookieAttributeHandler h2 = Mockito.mock(CommonCookieAttributeHandler.class);
309         Mockito.when(h2.getAttributeName()).thenReturn("Max-Age");
310 
311         final RFC6265CookieSpec cookiespec = new RFC6265CookieSpec(h1, h2);
312 
313         final Header header = new BasicHeader("Set-Cookie", "name = value ; expires = stuff; max-age = otherstuff;");
314         final CookieOrigin origin = new CookieOrigin("host", 80, "/path/", true);
315         cookiespec.parse(header, origin);
316 
317         Mockito.verify(h1, Mockito.never()).parse(ArgumentMatchers.<SetCookie>any(), ArgumentMatchers.anyString());
318         Mockito.verify(h2).parse(ArgumentMatchers.<SetCookie>any(), ArgumentMatchers.eq("otherstuff"));
319     }
320 
321 }