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.util.Cookie;
31  import org.htmlunit.util.MimeType;
32  import org.htmlunit.util.NameValuePair;
33  import org.junit.jupiter.api.Test;
34  
35  /**
36   * Unit tests for {@link CookieManager}.
37   *
38   * @author Ronald Brill
39   */
40  public class CookieManager5Test extends WebServerTestCase {
41  
42      /**
43       * @throws Exception if an error occurs
44       */
45      @Test
46      public void sameDomainWithClientCookie() throws Exception {
47          final List<NameValuePair> headers = new ArrayList<>();
48          getMockWebConnection().setDefaultResponse("something", 200, "Ok", MimeType.TEXT_HTML, headers);
49          startWebServer(getMockWebConnection());
50  
51          try (WebClient webClient = getWebClient()) {
52              webClient.getCookieManager().clearCookies();
53  
54              webClient.getPage(CookieManager4Test.URL_HOST3);
55              WebRequest lastRequest = getMockWebConnection().getLastWebRequest();
56              assertNull(lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
57  
58              final Cookie cookie = new Cookie(CookieManager4Test.DOMAIN, "name", "value");
59              webClient.getCookieManager().addCookie(cookie);
60              webClient.getPage(CookieManager4Test.URL_HOST3);
61              lastRequest = getMockWebConnection().getLastWebRequest();
62              assertEquals("name=value", lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
63          }
64      }
65  
66      /**
67       * @throws Exception if an error occurs
68       */
69      @Test
70      public void unqualifiedHostWithClientCookie() throws Exception {
71          final List<NameValuePair> headers = new ArrayList<>();
72          getMockWebConnection().setDefaultResponse("something", 200, "Ok", MimeType.TEXT_HTML, headers);
73          startWebServer(getMockWebConnection());
74  
75          try (WebClient webClient = getWebClient()) {
76              webClient.getCookieManager().clearCookies();
77  
78              webClient.getPage(CookieManager4Test.URL_HOST4);
79              WebRequest lastRequest = getMockWebConnection().getLastWebRequest();
80              assertNull(lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
81  
82              final Cookie cookie = new Cookie(CookieManager4Test.DOMAIN, "name", "value");
83              webClient.getCookieManager().addCookie(cookie);
84              webClient.getPage(CookieManager4Test.URL_HOST4);
85              lastRequest = getMockWebConnection().getLastWebRequest();
86              assertNull(lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
87          }
88      }
89  
90      /**
91       * @throws Exception if an error occurs
92       */
93      @Test
94      public void subdomainWithClientCookie() throws Exception {
95          final List<NameValuePair> headers = new ArrayList<>();
96          getMockWebConnection().setDefaultResponse("something", 200, "Ok", MimeType.TEXT_HTML, headers);
97          startWebServer(getMockWebConnection());
98  
99          try (WebClient webClient = getWebClient()) {
100             webClient.getCookieManager().clearCookies();
101 
102             webClient.getPage(CookieManager4Test.URL_HOST1);
103             WebRequest lastRequest = getMockWebConnection().getLastWebRequest();
104             assertNull(lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
105 
106             final Cookie cookie = new Cookie(CookieManager4Test.DOMAIN, "name", "value");
107             webClient.getCookieManager().addCookie(cookie);
108             webClient.getPage(CookieManager4Test.URL_HOST1);
109             lastRequest = getMockWebConnection().getLastWebRequest();
110             assertEquals("name=value", lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
111         }
112     }
113 
114     /**
115      * @throws Exception if an error occurs
116      */
117     @Test
118     public void differentSubdomainWithClientCookie() throws Exception {
119         final List<NameValuePair> headers = new ArrayList<>();
120         getMockWebConnection().setDefaultResponse("something", 200, "Ok", MimeType.TEXT_HTML, headers);
121         startWebServer(getMockWebConnection());
122 
123         try (WebClient webClient = getWebClient()) {
124             webClient.getCookieManager().clearCookies();
125 
126             webClient.getPage(CookieManager4Test.URL_HOST1);
127             WebRequest lastRequest = getMockWebConnection().getLastWebRequest();
128             assertNull(lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
129 
130             final Cookie cookie = new Cookie("host2." + CookieManager4Test.DOMAIN, "name", "value");
131             webClient.getCookieManager().addCookie(cookie);
132             webClient.getPage(CookieManager4Test.URL_HOST1);
133             lastRequest = getMockWebConnection().getLastWebRequest();
134             assertNull(lastRequest.getAdditionalHeaders().get(HttpHeader.COOKIE));
135         }
136     }
137 
138     /**
139      * Check the cookie expires gets overwritten.
140      *
141      * @throws Exception if the test fails
142      */
143     @Test
144     public void updateCookieExpiresWithClientCookie() throws Exception {
145         final Date date = new Date(System.currentTimeMillis() + 500_000);
146         final Map<String, Class<? extends Servlet>> servlets = new HashMap<>();
147         servlets.put(SetCookieExpires10Servlet.URL, SetCookieExpires10Servlet.class);
148         servlets.put(SetCookieExpires1000Servlet.URL, SetCookieExpires1000Servlet.class);
149         startWebServer("./", null, servlets);
150 
151         try (WebClient webClient = getWebClient()) {
152             webClient.getCookieManager().clearCookies();
153 
154             final Date expires = new Date(System.currentTimeMillis() + 10_000L);
155             Cookie cookie = new Cookie("localhost", "first", "1", null, expires, false, false);
156             webClient.getCookieManager().addCookie(cookie);
157 
158             assertEquals(1, webClient.getCookieManager().getCookies().size());
159             cookie = webClient.getCookieManager().getCookies().iterator().next();
160             assertFalse("" + cookie.getExpires(), cookie.getExpires().after(date));
161 
162             webClient.getPage("http://localhost:" + PORT + SetCookieExpires1000Servlet.URL);
163             assertEquals(1, webClient.getCookieManager().getCookies().size());
164             cookie = webClient.getCookieManager().getCookies().iterator().next();
165             assertTrue("" + cookie.getExpires(), cookie.getExpires().after(date));
166         }
167     }
168 
169 
170     /**
171      * Check the cookie expires gets overwritten.
172      *
173      * @throws Exception if the test fails
174      */
175     @Test
176     public void updateCookieExpires() throws Exception {
177         final Date date = new Date(System.currentTimeMillis() + 500_000);
178         final Map<String, Class<? extends Servlet>> servlets = new HashMap<>();
179         servlets.put(SetCookieExpires10Servlet.URL, SetCookieExpires10Servlet.class);
180         servlets.put(SetCookieExpires1000Servlet.URL, SetCookieExpires1000Servlet.class);
181         startWebServer("./", null, servlets);
182 
183         try (WebClient webClient = getWebClient()) {
184             webClient.getPage("http://localhost:" + PORT + SetCookieExpires10Servlet.URL);
185             assertEquals(1, webClient.getCookieManager().getCookies().size());
186             Cookie cookie = webClient.getCookieManager().getCookies().iterator().next();
187             assertFalse("" + cookie.getExpires(), cookie.getExpires().after(date));
188 
189             webClient.getPage("http://localhost:" + PORT + SetCookieExpires1000Servlet.URL);
190             assertEquals(1, webClient.getCookieManager().getCookies().size());
191             cookie = webClient.getCookieManager().getCookies().iterator().next();
192             assertTrue("" + cookie.getExpires(), cookie.getExpires().after(date));
193         }
194     }
195 
196     @Override
197     protected WebClient getWebClient() {
198         final WebClient webClient = super.getWebClient();
199         // set timeout to fail fast when the url not mapped
200         webClient.getOptions().setTimeout(1000);
201         return webClient;
202     }
203 
204     /**
205      * Helper class for {@link #updateCookieExpires}.
206      */
207     public abstract static class SetCookieExpiresServlet extends HttpServlet {
208         private static final String HTML_ = DOCTYPE_HTML
209                 + "<html><head></head>\n"
210                 + "<body>\n"
211                 + "</body></html>";
212 
213         protected abstract long getTimeout();
214 
215         /**
216          * {@inheritDoc}
217          */
218         @Override
219         protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
220             resp.setStatus(200);
221             final String expires = DateUtils.formatDate(new Date(System.currentTimeMillis() + getTimeout()));
222             resp.setHeader("Set-Cookie", "first=1; expires=" + expires + ";");
223             resp.getWriter().write(HTML_);
224         }
225     }
226 
227     /**
228      * Helper class for {@link #updateCookieExpires}.
229      */
230     public static class SetCookieExpires10Servlet extends SetCookieExpiresServlet {
231         static final String URL = "/test10";
232 
233         @Override
234         protected long getTimeout() {
235             return 10_000L;
236         }
237     }
238 
239     /**
240      * Helper class for {@link #updateCookieExpires}.
241      */
242     public static class SetCookieExpires1000Servlet extends SetCookieExpiresServlet {
243         static final String URL = "/test1000";
244 
245         @Override
246         protected long getTimeout() {
247             return 1_000_000L;
248         }
249     }
250 }