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.util;
16  
17  import java.util.regex.Matcher;
18  import java.util.regex.Pattern;
19  
20  import org.apache.commons.lang3.StringUtils;
21  import org.htmlunit.HttpHeader;
22  import org.htmlunit.WebResponse;
23  
24  /**
25   * @author Anton Demydenko
26   * @author Lai Quang Duong
27   */
28  public final class HeaderUtils {
29  
30      private static final String CACHE_CONTROL_PRIVATE = "private";
31      private static final String CACHE_CONTROL_PUBLIC = "public";
32      private static final String CACHE_CONTROL_NO_STORE = "no-store";
33      private static final String CACHE_CONTROL_NO_CACHE = "no-cache";
34      private static final String CACHE_CONTROL_MAX_AGE = "max-age";
35      private static final String CACHE_CONTROL_S_MAXAGE = "s-maxage";
36      private static final Pattern MAX_AGE_HEADER_PATTERN = Pattern.compile("^.*max-age=(\\d+).*$");
37      private static final Pattern S_MAXAGE_HEADER_PATTERN = Pattern.compile("^.*s-maxage=(\\d+).*$");
38  
39      private HeaderUtils() {
40          // utility class
41      }
42  
43      /**
44       * @param response {@code WebResponse}
45       * @return if 'Cache-Control' header is present and contains 'private' value
46       */
47      public static boolean containsPrivate(final WebResponse response) {
48          return containsCacheControlValue(response, CACHE_CONTROL_PRIVATE);
49      }
50  
51      /**
52       * @param response {@code WebResponse}
53       * @return if 'Cache-Control' header is present and contains 'public' value
54       */
55      public static boolean containsPublic(final WebResponse response) {
56          return containsCacheControlValue(response, CACHE_CONTROL_PUBLIC);
57      }
58  
59      /**
60       * @param response {@code WebResponse}
61       * @return if 'Cache-Control' header is present and contains 'no-store' value
62       */
63      public static boolean containsNoStore(final WebResponse response) {
64          return containsCacheControlValue(response, CACHE_CONTROL_NO_STORE);
65      }
66  
67      /**
68       * @param response {@code WebResponse}
69       * @return if 'Cache-Control' header is present and contains 'no-cache' value@return
70       */
71      public static boolean containsNoCache(final WebResponse response) {
72          return containsCacheControlValue(response, CACHE_CONTROL_NO_CACHE);
73      }
74  
75      /**
76       * @param response {@code WebResponse}
77       * @return if 'Etag' header is present
78       */
79      public static boolean containsETag(final WebResponse response) {
80          return response.getResponseHeaderValue(HttpHeader.ETAG) != null;
81      }
82  
83      /**
84       * @param response {@code WebResponse}
85       * @return if 'Last-Modified' header is present
86       */
87      public static boolean containsLastModified(final WebResponse response) {
88          return response.getResponseHeaderValue(HttpHeader.LAST_MODIFIED) != null;
89      }
90  
91      /**
92       * @param response {@code WebResponse}
93       * @return if 'Cache-Control' header is present and contains 's-maxage' value
94       */
95      public static boolean containsSMaxage(final WebResponse response) {
96          return containsCacheControlValue(response, CACHE_CONTROL_S_MAXAGE);
97      }
98  
99      /**
100      * @param response {@code WebResponse}
101      * @return if 'Cache-Control' header is present and contains 'max-age' value
102      */
103     public static boolean containsMaxAge(final WebResponse response) {
104         return containsCacheControlValue(response, CACHE_CONTROL_MAX_AGE);
105     }
106 
107     /**
108      * @param response {@code WebResponse}
109      * @return if 'Cache-Control' header is present and contains 'max-age' value
110      */
111     public static boolean containsMaxAgeOrSMaxage(final WebResponse response) {
112         final String cacheControl = response.getResponseHeaderValue(HttpHeader.CACHE_CONTROL);
113         if (StringUtils.contains(cacheControl, CACHE_CONTROL_MAX_AGE)) {
114             return true;
115         }
116         return StringUtils.contains(cacheControl, CACHE_CONTROL_S_MAXAGE);
117     }
118 
119     /**
120      * @param response {@code WebResponse}
121      * @return value of 's-maxage' directive and 0 if it is absent
122      */
123     public static long sMaxage(final WebResponse response) {
124         if (containsCacheControlValue(response, CACHE_CONTROL_S_MAXAGE)) {
125             return directiveValue(response, S_MAXAGE_HEADER_PATTERN);
126         }
127         return 0;
128     }
129 
130     /**
131      * @param response {@code WebResponse}
132      * @return value of 'max-age' directive and 0 if it is absent
133      */
134     public static long maxAge(final WebResponse response) {
135         if (containsCacheControlValue(response, CACHE_CONTROL_MAX_AGE)) {
136             return directiveValue(response, MAX_AGE_HEADER_PATTERN);
137         }
138 
139         return 0;
140     }
141 
142     private static long directiveValue(final WebResponse response, final Pattern pattern) {
143         final String value = response.getResponseHeaderValue(HttpHeader.CACHE_CONTROL);
144         if (value != null) {
145             final Matcher matcher = pattern.matcher(value);
146             if (matcher.matches()) {
147                 return Long.parseLong(matcher.group(1));
148             }
149         }
150 
151         return 0;
152     }
153 
154     private static boolean containsCacheControlValue(final WebResponse response, final String value) {
155         final String cacheControl = response.getResponseHeaderValue(HttpHeader.CACHE_CONTROL);
156         return StringUtils.contains(cacheControl, value);
157     }
158 }