org.codehaus.httpcache4j.HeaderUtils Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2008, The Codehaus. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.codehaus.httpcache4j;
import org.codehaus.httpcache4j.util.OptionalUtils;
import org.codehaus.httpcache4j.util.Preconditions;
import static org.codehaus.httpcache4j.HeaderConstants.*;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Locale;
import java.util.stream.Collectors;
/**
* A collection header utilities.
*/
public final class HeaderUtils {
public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss 'GMT'";
private static final String NO_CACHE_HEADER_VALUE = "no-cache";
private static final Header VARY_ALL = new Header(VARY, "*");
private static List UNCACHEABLE_HEADERS = Arrays.asList(
HeaderConstants.SET_COOKIE,
HeaderConstants.PROXY_AUTHENTICATE,
HeaderConstants.WWW_AUTHENTICATE
);
private HeaderUtils() {
}
public static Optional fromHttpDate(Header header) {
if (header == null) {
return null;
}
if ("0".equals(header.getValue().trim())) {
return Optional.of(LocalDateTime.of(LocalDate.of(1970, 1, 1), LocalTime.of(0, 0, 0, 0)));
}
return parseGMTString(header.getValue());
}
public static Optional parseGMTString(String value) {
DateTimeFormatter formatter = getFormatter();
try {
return Optional.of(LocalDateTime.from(formatter.parse(value)));
} catch (DateTimeParseException ignore) {
}
return Optional.empty();
}
public static Header toHttpDate(String headerName, LocalDateTime time) {
return new Header(headerName, toGMTString(time));
}
public static String toGMTString(LocalDateTime time) {
DateTimeFormatter formatter = getFormatter();
return formatter.format(time);
}
private static DateTimeFormatter getFormatter() {
return DateTimeFormatter.ofPattern(PATTERN_RFC1123).
withZone(ZoneId.of("UTC")).
withLocale(Locale.US);
}
public static long getHeaderAsDate(Header header) {
try {
Optional dateTime = fromHttpDate(header);
if (dateTime.isPresent()) {
return dateTime.get().toInstant(ZoneOffset.UTC).toEpochMilli();
}
}
catch (Exception e) {
return -1;
}
return -1;
}
static Headers cleanForCaching(Headers headers) {
for (String headerName : UNCACHEABLE_HEADERS) {
headers = headers.remove(headerName);
}
return headers;
}
/**
* From http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4.
*
* Unless specifically constrained by a cache-control (section 14.9) directive,
* a caching system MAY always store a successful response (see section 13.8)
* as a cache entry, MAY return it without validation if it is fresh, and MAY return it
* after successful validation. If there is neither a cache validator nor an explicit
* expiration time associated with a response, we do not expect it to be cached,
* but certain caches MAY violate this expectation
* (for example, when little or no network connectivity is available).
* A client can usually detect that such a response was taken from a cache by comparing
* the Date header to the current time.
*
* @param headers the headers to analyze
* @return {@code true} if the headers were cacheable, {@code false} if not.
*/
public static boolean hasCacheableHeaders(Headers headers) {
if (headers.contains(VARY_ALL)) {
return false;
}
if (headers.contains(CACHE_CONTROL)) {
Optional cc = headers.getCacheControl();
if (OptionalUtils.exists(cc, (cc2 -> cc2.isNoCache() || cc2.isNoStore()))) {
return false;
}
}
if (headers.contains(PRAGMA)) {
Optional header = headers.getFirstHeaderValue(PRAGMA);
if (OptionalUtils.exists(header, s -> s.contains(NO_CACHE_HEADER_VALUE))) {
return false;
}
}
if (headers.contains(EXPIRES)) {
Optional expires = headers.getExpires();
Optional date = headers.getDate();
if (!expires.isPresent() || !date.isPresent()) {
return false;
}
if (OptionalUtils.exists(expires, e -> e.isBefore(date.get())) || OptionalUtils.exists(expires, e -> e.isEqual(date.get()))) {
return false;
}
}
return true;
}
static String removeQuotes(String value) {
if (value != null && value.startsWith("\"") && value.endsWith("\"")) {
return value.substring(1, value.length() - 1);
}
return value;
}
public static Header toLinkHeader(List linkDirectives) {
StringBuilder builder = new StringBuilder();
for (LinkDirective linkDirective : linkDirectives) {
if (builder.length() > 0) {
builder.append(", ");
}
builder.append(linkDirective);
}
return new Header(LINK_HEADER, builder.toString());
}
public static List toLinkDirectives(Header header) {
Preconditions.checkArgument(!LINK_HEADER.equals(header.getName()), "This must be a \"Link\" header");
return header.getDirectives().stream().
filter(d -> d instanceof LinkDirective).
map(d -> (LinkDirective) d).
collect(Collectors.toList());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy