View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit;
16  
17  import java.io.IOException;
18  import java.util.ArrayList;
19  import java.util.Date;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  import javax.servlet.Servlet;
25  import javax.servlet.http.HttpServlet;
26  import javax.servlet.http.HttpServletRequest;
27  import javax.servlet.http.HttpServletResponse;
28  
29  import org.apache.http.client.utils.DateUtils;
30  import org.htmlunit.junit.BrowserRunner;
31  import org.htmlunit.util.Cookie;
32  import org.htmlunit.util.MimeType;
33  import org.htmlunit.util.NameValuePair;
34  import org.junit.Test;
35  import org.junit.runner.RunWith;
36  
37  /**
38   * Unit tests for {@link CookieManager}.
39   *
40   * @author Ronald Brill
41   */
42  @RunWith(BrowserRunner.class)
43  public class CookieManager5Test extends WebServerTestCase {
44  
45      /**
46       * @throws Exception if an error occurs
47       */
48      @Test
49      public void sameDomainWithClientCookie() throws Exception {
50          final List<NameValuePair> headers = new ArrayList<>();
51          getMockWebConnection().setDefaultResponse("something", 200, "Ok", MimeType.TEXT_HTML, headers);
52          startWebServer(getMockWebConnection());
53  
54          try (WebClient webClient = getWebClient()) {
55              webClient.getCookieManager().clearCookies();
56  
57              webClient.getPage(CookieManager4Test.URL_HOST3);
58              WebRequest lastRequest = getMockWebConnection().getLastWebRequest();
59              assertNull(lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
60  
61              final Cookie cookie = new Cookie(CookieManager4Test.DOMAIN, "name", "value");
62              webClient.getCookieManager().addCookie(cookie);
63              webClient.getPage(CookieManager4Test.URL_HOST3);
64              lastRequest = getMockWebConnection().getLastWebRequest();
65              assertEquals("name=value", lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
66          }
67      }
68  
69      /**
70       * @throws Exception if an error occurs
71       */
72      @Test
73      public void unqualifiedHostWithClientCookie() throws Exception {
74          final List<NameValuePair> headers = new ArrayList<>();
75          getMockWebConnection().setDefaultResponse("something", 200, "Ok", MimeType.TEXT_HTML, headers);
76          startWebServer(getMockWebConnection());
77  
78          try (WebClient webClient = getWebClient()) {
79              webClient.getCookieManager().clearCookies();
80  
81              webClient.getPage(CookieManager4Test.URL_HOST4);
82              WebRequest lastRequest = getMockWebConnection().getLastWebRequest();
83              assertNull(lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
84  
85              final Cookie cookie = new Cookie(CookieManager4Test.DOMAIN, "name", "value");
86              webClient.getCookieManager().addCookie(cookie);
87              webClient.getPage(CookieManager4Test.URL_HOST4);
88              lastRequest = getMockWebConnection().getLastWebRequest();
89              assertNull(lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
90          }
91      }
92  
93      /**
94       * @throws Exception if an error occurs
95       */
96      @Test
97      public void subdomainWithClientCookie() throws Exception {
98          final List<NameValuePair> headers = new ArrayList<>();
99          getMockWebConnection().setDefaultResponse("something", 200, "Ok", MimeType.TEXT_HTML, headers);
100         startWebServer(getMockWebConnection());
101 
102         try (WebClient webClient = getWebClient()) {
103             webClient.getCookieManager().clearCookies();
104 
105             webClient.getPage(CookieManager4Test.URL_HOST1);
106             WebRequest lastRequest = getMockWebConnection().getLastWebRequest();
107             assertNull(lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
108 
109             final Cookie cookie = new Cookie(CookieManager4Test.DOMAIN, "name", "value");
110             webClient.getCookieManager().addCookie(cookie);
111             webClient.getPage(CookieManager4Test.URL_HOST1);
112             lastRequest = getMockWebConnection().getLastWebRequest();
113             assertEquals("name=value", lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
114         }
115     }
116 
117     /**
118      * @throws Exception if an error occurs
119      */
120     @Test
121     public void differentSubdomainWithClientCookie() throws Exception {
122         final List<NameValuePair> headers = new ArrayList<>();
123         getMockWebConnection().setDefaultResponse("something", 200, "Ok", MimeType.TEXT_HTML, headers);
124         startWebServer(getMockWebConnection());
125 
126         try (WebClient webClient = getWebClient()) {
127             webClient.getCookieManager().clearCookies();
128 
129             webClient.getPage(CookieManager4Test.URL_HOST1);
130             WebRequest lastRequest = getMockWebConnection().getLastWebRequest();
131             assertNull(lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
132 
133             final Cookie cookie = new Cookie("host2." + CookieManager4Test.DOMAIN, "name", "value");
134             webClient.getCookieManager().addCookie(cookie);
135             webClient.getPage(CookieManager4Test.URL_HOST1);
136             lastRequest = getMockWebConnection().getLastWebRequest();
137             assertNull(lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
138         }
139     }
140 
141     /**
142      * Check the cookie expires gets overwritten.
143      *
144      * @throws Exception if the test fails
145      */
146     @Test
147     public void updateCookieExpiresWithClientCookie() throws Exception {
148         final Date date = new Date(System.currentTimeMillis() + 500_000);
149         final Map<String, Class<? extends Servlet>> servlets = new HashMap<>();
150         servlets.put(SetCookieExpires10Servlet.URL, SetCookieExpires10Servlet.class);
151         servlets.put(SetCookieExpires1000Servlet.URL, SetCookieExpires1000Servlet.class);
152         startWebServer("./", null, servlets);
153 
154         try (WebClient webClient = getWebClient()) {
155             webClient.getCookieManager().clearCookies();
156 
157             final Date expires = new Date(System.currentTimeMillis() + 10_000L);
158             Cookie cookie = new Cookie("localhost", "first", "1", null, expires, false, false);
159             webClient.getCookieManager().addCookie(cookie);
160 
161             assertEquals(1, webClient.getCookieManager().getCookies().size());
162             cookie = webClient.getCookieManager().getCookies().iterator().next();
163             assertFalse("" + cookie.getExpires(), cookie.getExpires().after(date));
164 
165             webClient.getPage("http://localhost:" + PORT + SetCookieExpires1000Servlet.URL);
166             assertEquals(1, webClient.getCookieManager().getCookies().size());
167             cookie = webClient.getCookieManager().getCookies().iterator().next();
168             assertTrue("" + cookie.getExpires(), cookie.getExpires().after(date));
169         }
170     }
171 
172 
173     /**
174      * Check the cookie expires gets overwritten.
175      *
176      * @throws Exception if the test fails
177      */
178     @Test
179     public void updateCookieExpires() throws Exception {
180         final Date date = new Date(System.currentTimeMillis() + 500_000);
181         final Map<String, Class<? extends Servlet>> servlets = new HashMap<>();
182         servlets.put(SetCookieExpires10Servlet.URL, SetCookieExpires10Servlet.class);
183         servlets.put(SetCookieExpires1000Servlet.URL, SetCookieExpires1000Servlet.class);
184         startWebServer("./", null, servlets);
185 
186         try (WebClient webClient = getWebClient()) {
187             webClient.getPage("http://localhost:" + PORT + SetCookieExpires10Servlet.URL);
188             assertEquals(1, webClient.getCookieManager().getCookies().size());
189             Cookie cookie = webClient.getCookieManager().getCookies().iterator().next();
190             assertFalse("" + cookie.getExpires(), cookie.getExpires().after(date));
191 
192             webClient.getPage("http://localhost:" + PORT + SetCookieExpires1000Servlet.URL);
193             assertEquals(1, webClient.getCookieManager().getCookies().size());
194             cookie = webClient.getCookieManager().getCookies().iterator().next();
195             assertTrue("" + cookie.getExpires(), cookie.getExpires().after(date));
196         }
197     }
198 
199     @Override
200     protected WebClient getWebClient() {
201         final WebClient webClient = super.getWebClient();
202         // set timeout to fail fast when the url not mapped
203         webClient.getOptions().setTimeout(1000);
204         return webClient;
205     }
206 
207     /**
208      * Helper class for {@link #updateCookieExpires}.
209      */
210     public abstract static class SetCookieExpiresServlet extends HttpServlet {
211         private static final String HTML_ = DOCTYPE_HTML
212                 + "<html><head></head>\n"
213                 + "<body>\n"
214                 + "</body></html>";
215 
216         protected abstract long getTimeout();
217 
218         /**
219          * {@inheritDoc}
220          */
221         @Override
222         protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
223             resp.setStatus(200);
224             final String expires = DateUtils.formatDate(new Date(System.currentTimeMillis() + getTimeout()));
225             resp.setHeader("Set-Cookie", "first=1; expires=" + expires + ";");
226             resp.getWriter().write(HTML_);
227         }
228     }
229 
230     /**
231      * Helper class for {@link #updateCookieExpires}.
232      */
233     public static class SetCookieExpires10Servlet extends SetCookieExpiresServlet {
234         static final String URL = "/test10";
235 
236         @Override
237         protected long getTimeout() {
238             return 10_000L;
239         }
240     }
241 
242     /**
243      * Helper class for {@link #updateCookieExpires}.
244      */
245     public static class SetCookieExpires1000Servlet extends SetCookieExpiresServlet {
246         static final String URL = "/test1000";
247 
248         @Override
249         protected long getTimeout() {
250             return 1_000_000L;
251         }
252     }
253 }