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

net.dongliu.cute.http.Headers Maven / Gradle / Ivy

The newest version!
package net.dongliu.cute.http;


import net.dongliu.commons.Lazy;
import net.dongliu.commons.Optionals;
import net.dongliu.commons.collection.Lists;
import net.dongliu.commons.collection.Maps;

import java.net.HttpCookie;
import java.net.http.HttpHeaders;
import java.time.Instant;
import java.util.*;

import static java.util.Collections.unmodifiableMap;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toUnmodifiableList;

/**
 * The http headers.
 * This class is thread-safe.
 *
 * @author Liu Dong
 */
public class Headers {
    private final Map> map;
    private final Lazy cookies;
    private final Lazy> contentType;

    /**
     * Create a new Headers.
     *
     * @param map the headers map
     */
    private Headers(Map> map) {
        this.map = requireNonNull(map);
        this.cookies = Lazy.of(this::parseCookies);
        this.contentType = Lazy.of(() -> getHeader(HeaderNames.CONTENT_TYPE).flatMap(ContentType::safeParse));
    }

    /**
     * Construct a headers, from immutable jdk http client headers.
     *
     * @param httpHeaders the http headers
     * @return Headers
     */
    public static Headers ofHttpHeaders(HttpHeaders httpHeaders) {
        return new Headers(httpHeaders.map());
    }

    /**
     * Construct headers from a Collection of header.
     *
     * @param headers the header collection
     * @return Headers
     */
    public static Headers of(Collection headers) {
        var map = Maps.>newCaseInsensitiveMap();
        for (var header : headers) {
            map.computeIfAbsent(header.name(), name -> new ArrayList<>(2)).add(header.value());
        }
        return new Headers(copyImmutable(map));
    }

    // copy map to a new immutable, case-insensitive map
    private static Map> copyImmutable(Map> map) {
        var newMap = Maps.>newCaseInsensitiveMap();
        for (var entry : map.entrySet()) {
            newMap.put(entry.getKey(), List.copyOf(entry.getValue()));
        }
        return unmodifiableMap(newMap);
    }

    private Cookies parseCookies() {
        var cookieValues = getHeaders(HeaderNames.SET_COOKIE);
        // hope timestamp do not diff too much
        var createTime = Instant.now();
        var cookieList = cookieValues.stream()
                .flatMap(v -> HttpCookie.parse(v).stream())
                .map(c -> ofHttpCookie(createTime, c))
                .collect(toUnmodifiableList());
        return new Cookies(cookieList);
    }

    private static Cookie ofHttpCookie(Instant createTime, HttpCookie httpCookie) {
        return new Cookie(httpCookie.getName(), httpCookie.getValue(), httpCookie.getDomain(), httpCookie.getPath(),
                httpCookie.getMaxAge() < 0 ? OptionalLong.empty() : OptionalLong.of(httpCookie.getMaxAge()),
                httpCookie.getSecure(), httpCookie.isHttpOnly(), createTime);
    }

    /**
     * Get headers by name. If not exists, return empty list
     */
    public List getHeaders(String name) {
        requireNonNull(name);
        return map.getOrDefault(name, List.of());
    }

    /**
     * Get the first header value matched name.
     */
    public Optional getHeader(String name) {
        requireNonNull(name);
        return Lists.first(getHeaders(name));
    }

    /**
     * Get header value as long.
     */
    public OptionalLong getLongHeader(String name) {
        var header = getHeader(name);
        return Optionals.mapToLong(header, Long::parseLong);
    }

    /**
     * Get all header as Map
     *
     * @return immutable map of headers. return empty map if do not has any header.
     */
    public Map> allHeaders() {
        return map;
    }

    /**
     * Get content type set in http header.
     * If do not set Content-Type header, or parse header error, return empty Optional.
     *
     * @return the charset
     */
    public Optional contentType() {
        return contentType.get();
    }

    /**
     * Get cookies in this header.
     *
     * @return a immutable list of cookies
     */
    public Cookies cookies() {
        return cookies.get();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy