All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cz.jirutka.spring.http.client.cache.DefaultResponseExpirationResolver Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014 Jakub Jirutka .
 *
 * 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 cz.jirutka.spring.http.client.cache;

import cz.jirutka.spring.http.client.cache.internal.CacheControl;
import net.jcip.annotations.Immutable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.ClientHttpResponse;

import java.util.Date;

import static java.lang.Math.max;
import static org.apache.commons.lang3.math.NumberUtils.toLong;

@Immutable
public class DefaultResponseExpirationResolver implements ResponseExpirationResolver {

    /**
     * @see HTTP/1.1 section 14.6
     */
    public static final long MAX_AGE = 2147483648L;

    private final boolean sharedCache;


    public DefaultResponseExpirationResolver() {
        this(true);
    }

    public DefaultResponseExpirationResolver(boolean sharedCache) {
        this.sharedCache = sharedCache;
    }


    public Date resolveExpirationDate(ClientHttpResponse response, Date correctedInitialDate) {
        long maxAge = parseMaxAgeHeader(response.getHeaders()) * 1000L; //ms

        return new Date(correctedInitialDate.getTime() + maxAge);
    }

    public Date resolveInitialDate(ClientHttpResponse response, Date requestDate, Date responseDate) {
        long age = correctedInitialAge(response, requestDate, responseDate) * 1000L; //ms

        return new Date(responseDate.getTime() + age);
    }

    /**
     * Calculates a corrected initial age of the request, i.e. number of seconds
     * the response was created before we received it.
     *
     * @param response The response to compute initial age of.
     * @param requestDate When the request was send.
     * @param responseDate When the response was received.
     * @return A corrected initial age in seconds.
     *
     * @see HTTP/1.1 section 13
     */
    public long correctedInitialAge(ClientHttpResponse response, Date requestDate, Date responseDate) {
        long ageValue = parseAgeHeader(response.getHeaders());
        long headerDate = response.getHeaders().getDate();

        long apparentAge = max(0, responseDate.getTime() - headerDate) / 1000L; //seconds
        long correctedReceivedAge = max(apparentAge, ageValue);
        long responseDelay = (responseDate.getTime() - requestDate.getTime()) / 1000L; //seconds

        return correctedReceivedAge + responseDelay;
    }

    /**
     * Parses value of the Age header from the given headers. When
     * the header is not specified, returns 0. When the header is specified
     * multiple times, then returns greater value. If the value is less then
     * zero or malformed, then {@link #MAX_AGE} is returned.
     *
     * @param headers HTTP headers of the response.
     * @return An Age header value.
     */
    long parseAgeHeader(HttpHeaders headers) {
        long result = 0;

        if (!headers.containsKey("Age")) {
            return result;
        }
        for (String value : headers.get("Age")) {
            long age = toLong(value, MAX_AGE);
            if (age < 0) age = MAX_AGE;

            result = max(result, age);
        }
        return result;
    }

    private int parseMaxAgeHeader(HttpHeaders headers) {
        CacheControl cc = CacheControl.valueOf(headers.getCacheControl());
        return cc.getMaxAge(sharedCache);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy