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

io.micronaut.http.HttpHeaders Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017-2020 original authors
 *
 * 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
 *
 * https://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 io.micronaut.http;

import io.micronaut.core.convert.ConversionContext;
import io.micronaut.core.type.Headers;
import io.micronaut.http.util.HttpHeadersUtil;
import jakarta.annotation.Nullable;

import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.OptionalLong;

/**
 * Constants for common HTTP headers. See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html.
 *
 * @author Graeme Rocher
 * @since 1.0
 */
public interface HttpHeaders extends Headers {

    /**
     * {@code "Accept"}.
     */
    String ACCEPT = "Accept";

    /**
     * {@code "Accept-CH"}.
     */
    String ACCEPT_CH = "Accept-CH";

    /**
     * {@code "Accept-CH"}.
     */
    String ACCEPT_CH_LIFETIME = "Accept-CH-Lifetime";

    /**
     * {@code "Accept-Charset"}.
     */
    String ACCEPT_CHARSET = "Accept-Charset";

    /**
     * {@code "Accept-Encoding"}.
     */
    String ACCEPT_ENCODING = "Accept-Encoding";

    /**
     * {@code "Accept-Language"}.
     */
    String ACCEPT_LANGUAGE = "Accept-Language";

    /**
     * {@code "Accept-Ranges"}.
     */
    String ACCEPT_RANGES = "Accept-Ranges";

    /**
     * {@code "Accept-Patch"}.
     */
    String ACCEPT_PATCH = "Accept-Patch";

    /**
     * {@code "Access-Control-Allow-Credentials"}.
     */
    String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";

    /**
     * {@code "Access-Control-Allow-Headers"}.
     */
    String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";

    /**
     * {@code "Access-Control-Allow-Methods"}.
     */
    String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";

    /**
     * {@code "Access-Control-Allow-Origin"}.
     */
    String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";

    /**
     * {@code "Access-Control-Allow-Private-Network"}.
     * @see Private Network Access
     * @since 4.3.0
     */
    String ACCESS_CONTROL_ALLOW_PRIVATE_NETWORK = "Access-Control-Allow-Private-Network";

    /**
     * {@code "Access-Control-Expose-Headers"}.
     */
    String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";

    /**
     * {@code "Access-Control-Max-Age"}.
     */
    String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";

    /**
     * {@code "Access-Control-Request-Headers"}.
     */
    String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";

    /**
     * {@code "Access-Control-Request-Method"}.
     */
    String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method";

    /**
     * {@code "Access-Control-Request-Private-Network"}.
     * @see Private Network Access
     * @since 4.3.0
     */
    String ACCESS_CONTROL_REQUEST_PRIVATE_NETWORK = "Access-Control-Request-Private-Network";

    /**
     * {@code "Age"}.
     */
    String AGE = "Age";

    /**
     * {@code "Allow"}.
     */
    String ALLOW = "Allow";

    /**
     * {@code "Authorization"}.
     */
    String AUTHORIZATION = "Authorization";

    /**
     * {@code "Authorization"}.
     */
    String AUTHORIZATION_INFO = "Authorization-Info";

    /**
     * {@code "Cache-Control"}.
     */
    String CACHE_CONTROL = "Cache-Control";

    /**
     * {@code "Connection"}.
     */
    String CONNECTION = "Connection";

    /**
     * {@code "Content-Base"}.
     */
    String CONTENT_BASE = "Content-Base";

    /**
     * {@code "Content-Disposition"}.
     */
    String CONTENT_DISPOSITION = "Content-Disposition";

    /**
     * {@code "Content-DPR"}.
     */
    String CONTENT_DPR = "Content-DPR";

    /**
     * {@code "Content-Encoding"}.
     */
    String CONTENT_ENCODING = "Content-Encoding";

    /**
     * {@code "Content-Language"}.
     */
    String CONTENT_LANGUAGE = "Content-Language";

    /**
     * {@code "Content-Length"}.
     */
    String CONTENT_LENGTH = "Content-Length";

    /**
     * {@code "Content-Location"}.
     */
    String CONTENT_LOCATION = "Content-Location";

    /**
     * {@code "Content-Transfer-Encoding"}.
     */
    String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";

    /**
     * {@code "Content-MD5"}.
     */
    String CONTENT_MD5 = "Content-MD5";

    /**
     * {@code "Content-Range"}.
     */
    String CONTENT_RANGE = "Content-Range";

    /**
     * {@code "Content-Type"}.
     */
    String CONTENT_TYPE = "Content-Type";

    /**
     * {@code "Cookie"}.
     */
    String COOKIE = "Cookie";

    /**
     * {@code "Cross-Origin-Resource-Policy"}.
     */
    String CROSS_ORIGIN_RESOURCE_POLICY = "Cross-Origin-Resource-Policy";

    /**
     * {@code "Date"}.
     */
    String DATE = "Date";

    /**
     * {@code "Device-Memory"}.
     */
    String DEVICE_MEMORY = "Device-Memory";

    /**
     * {@code "Downlink"}.
     */
    String DOWNLINK = "Downlink";

    /**
     * {@code "DPR"}.
     */
    String DPR = "DPR";

    /**
     * {@code "ECT"}.
     */
    String ECT = "ECT";

    /**
     * {@code "ETag"}.
     */
    String ETAG = "ETag";

    /**
     * {@code "Expect"}.
     */
    String EXPECT = "Expect";

    /**
     * {@code "Expires"}.
     */
    String EXPIRES = "Expires";

    /**
     * {@code "Feature-Policy"}.
     */
    String FEATURE_POLICY = "Feature-Policy";

    /**
     * {@code "Forwarded"}.
     */
    String FORWARDED = "Forwarded";

    /**
     * {@code "From"}.
     */
    String FROM = "From";

    /**
     * {@code "Host"}.
     */
    String HOST = "Host";

    /**
     * {@code "If-Match"}.
     */
    String IF_MATCH = "If-Match";

    /**
     * {@code "If-Modified-Since"}.
     */
    String IF_MODIFIED_SINCE = "If-Modified-Since";

    /**
     * {@code "If-None-Match"}.
     */
    String IF_NONE_MATCH = "If-None-Match";

    /**
     * {@code "If-Range"}.
     */
    String IF_RANGE = "If-Range";

    /**
     * {@code "If-Unmodified-Since"}.
     */
    String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";

    /**
     * {@code "Last-Modified"}.
     */
    String LAST_MODIFIED = "Last-Modified";

    /**
     * {@code "Link"}.
     */
    String LINK = "Link";

    /**
     * {@code "Location"}.
     */
    String LOCATION = "Location";

    /**
     * {@code "Max-Forwards"}.
     */
    String MAX_FORWARDS = "Max-Forwards";

    /**
     * {@code "Origin"}.
     */
    String ORIGIN = "Origin";

    /**
     * {@code "Pragma"}.
     */
    String PRAGMA = "Pragma";

    /**
     * {@code "Proxy-Authenticate"}.
     */
    String PROXY_AUTHENTICATE = "Proxy-Authenticate";

    /**
     * {@code "Proxy-Authorization"}.
     */
    String PROXY_AUTHORIZATION = "Proxy-Authorization";

    /**
     * {@code "Range"}.
     */
    String RANGE = "Range";

    /**
     * {@code "Referer"}.
     */
    String REFERER = "Referer";

    /**
     * {@code "Referrer-Policy"}.
     */
    String REFERRER_POLICY = "Referrer-Policy";

    /**
     * {@code "Retry-After"}.
     */
    String RETRY_AFTER = "Retry-After";

    /**
     * {@code "RTT"}.
     */
    String RTT = "RTT";

    /**
     * {@code "Save-Data"}.
     */
    String SAVE_DATA = "Save-Data";

    /**
     * {@code "Sec-WebSocket-Key1"}.
     */
    String SEC_WEBSOCKET_KEY1 = "Sec-WebSocket-Key1";

    /**
     * {@code "Sec-WebSocket-Key2"}.
     */
    String SEC_WEBSOCKET_KEY2 = "Sec-WebSocket-Key2";

    /**
     * {@code "Sec-WebSocket-Location"}.
     */
    String SEC_WEBSOCKET_LOCATION = "Sec-WebSocket-Location";

    /**
     * {@code "Sec-WebSocket-Origin"}.
     */
    String SEC_WEBSOCKET_ORIGIN = "Sec-WebSocket-Origin";

    /**
     * {@code "Sec-WebSocket-Protocol"}.
     */
    String SEC_WEBSOCKET_PROTOCOL = "Sec-WebSocket-Protocol";

    /**
     * {@code "Sec-WebSocket-Version"}.
     */
    String SEC_WEBSOCKET_VERSION = "Sec-WebSocket-Version";

    /**
     * {@code "Sec-WebSocket-Key"}.
     */
    String SEC_WEBSOCKET_KEY = "Sec-WebSocket-Key";

    /**
     * {@code "Sec-WebSocket-Accept"}.
     */
    String SEC_WEBSOCKET_ACCEPT = "Sec-WebSocket-Accept";

    /**
     * {@code "Server"}.
     */
    String SERVER = "Server";

    /**
     * {@code "Set-Cookie"}.
     */
    String SET_COOKIE = "Set-Cookie";

    /**
     * {@code "Set-Cookie2"}.
     */
    String SET_COOKIE2 = "Set-Cookie2";

    /**
     * {@code "Source-Map"}.
     */
    String SOURCE_MAP = "SourceMap";

    /**
     * {@code "TE"}.
     */
    String TE = "TE";

    /**
     * {@code "Trailer"}.
     */
    String TRAILER = "Trailer";

    /**
     * {@code "Transfer-Encoding"}.
     */
    String TRANSFER_ENCODING = "Transfer-Encoding";

    /**
     * {@code "Upgrade"}.
     */
    String UPGRADE = "Upgrade";

    /**
     * {@code "User-Agent"}.
     */
    String USER_AGENT = "User-Agent";

    /**
     * {@code "Vary"}.
     */
    String VARY = "Vary";

    /**
     * {@code "Via"}.
     */
    String VIA = "Via";

    /**
     * {@code "Viewport-Width"}.
     */
    String VIEWPORT_WIDTH = "Viewport-Width";

    /**
     * {@code "Warning"}.
     */
    String WARNING = "Warning";

    /**
     * {@code "WebSocket-Location"}.
     */
    String WEBSOCKET_LOCATION = "WebSocket-Location";

    /**
     * {@code "WebSocket-Origin"}.
     */
    String WEBSOCKET_ORIGIN = "WebSocket-Origin";

    /**
     * {@code "WebSocket-Protocol"}.
     */
    String WEBSOCKET_PROTOCOL = "WebSocket-Protocol";

    /**
     * {@code "Width"}.
     */
    String WIDTH = "Width";

    /**
     * {@code "WWW-Authenticate"}.
     */
    String WWW_AUTHENTICATE = "WWW-Authenticate";

    /**
     * {@code "X-Auth-Token"}.
     */
    String X_AUTH_TOKEN = "X-Auth-Token";

    /**
     * Unmodifiable List of every header constant defined in {@link HttpHeaders}.
     */
    List STANDARD_HEADERS = Collections.unmodifiableList(Arrays.asList(
        ACCEPT,
        ACCEPT,
        ACCEPT_CH,
        ACCEPT_CH_LIFETIME,
        ACCEPT_CHARSET,
        ACCEPT_ENCODING,
        ACCEPT_LANGUAGE,
        ACCEPT_RANGES,
        ACCEPT_PATCH,
        ACCESS_CONTROL_ALLOW_CREDENTIALS,
        ACCESS_CONTROL_ALLOW_HEADERS,
        ACCESS_CONTROL_ALLOW_METHODS,
        ACCESS_CONTROL_ALLOW_ORIGIN,
        ACCESS_CONTROL_EXPOSE_HEADERS,
        ACCESS_CONTROL_MAX_AGE,
        ACCESS_CONTROL_REQUEST_HEADERS,
        ACCESS_CONTROL_REQUEST_METHOD,
        ACCESS_CONTROL_REQUEST_PRIVATE_NETWORK,
        AGE,
        ALLOW,
        AUTHORIZATION,
        AUTHORIZATION_INFO,
        CACHE_CONTROL,
        CONNECTION,
        CONTENT_BASE,
        CONTENT_DISPOSITION,
        CONTENT_DPR,
        CONTENT_ENCODING,
        CONTENT_LANGUAGE,
        CONTENT_LENGTH,
        CONTENT_LOCATION,
        CONTENT_TRANSFER_ENCODING,
        CONTENT_MD5,
        CONTENT_RANGE,
        CONTENT_TYPE,
        COOKIE,
        CROSS_ORIGIN_RESOURCE_POLICY,
        DATE,
        DEVICE_MEMORY,
        DOWNLINK,
        DPR,
        ECT,
        ETAG,
        EXPECT,
        EXPIRES,
        FEATURE_POLICY,
        FORWARDED,
        FROM,
        HOST,
        IF_MATCH,
        IF_MODIFIED_SINCE,
        IF_NONE_MATCH,
        IF_RANGE,
        IF_UNMODIFIED_SINCE,
        LAST_MODIFIED,
        LINK,
        LOCATION,
        MAX_FORWARDS,
        ORIGIN,
        PRAGMA,
        PROXY_AUTHENTICATE,
        PROXY_AUTHORIZATION,
        RANGE,
        REFERER,
        REFERRER_POLICY,
        RETRY_AFTER,
        RTT,
        SAVE_DATA,
        SEC_WEBSOCKET_KEY1,
        SEC_WEBSOCKET_KEY2,
        SEC_WEBSOCKET_LOCATION,
        SEC_WEBSOCKET_ORIGIN,
        SEC_WEBSOCKET_PROTOCOL,
        SEC_WEBSOCKET_VERSION,
        SEC_WEBSOCKET_KEY,
        SEC_WEBSOCKET_ACCEPT,
        SERVER,
        SET_COOKIE,
        SET_COOKIE2,
        SOURCE_MAP,
        TE,
        TRAILER,
        TRANSFER_ENCODING,
        UPGRADE,
        USER_AGENT,
        VARY,
        VIA,
        VIEWPORT_WIDTH,
        WARNING,
        WEBSOCKET_LOCATION,
        WEBSOCKET_ORIGIN,
        WEBSOCKET_PROTOCOL,
        WIDTH,
        WWW_AUTHENTICATE,
        X_AUTH_TOKEN
    ));

    /**
     * Whether the given key is contained within these values.
     *
     * @param name The key name
     * @return True if it is
     * @since 4.8.0
     */
    default boolean contains(CharSequence name) {
        return contains(name.toString());
    }

    /**
     * Obtain the date header.
     *
     * @param name The header name
     * @return The date header as a {@link ZonedDateTime} otherwise if it is not present or cannot be parsed
     * {@link Optional#empty()}
     */
    default Optional findDate(CharSequence name) {
        try {
            return findFirst(name).map(str -> {
                    LocalDateTime localDateTime = LocalDateTime.parse(str, DateTimeFormatter.RFC_1123_DATE_TIME);
                    return ZonedDateTime.of(localDateTime, ZoneId.of("GMT"));
                }

            );
        } catch (DateTimeParseException e) {
            return Optional.empty();
        }
    }

    /**
     * Obtain the date header.
     *
     * @param name The header name
     * @return The date header as a {@link ZonedDateTime} otherwise if it is not present or cannot be parsed null
     */
    default ZonedDateTime getDate(CharSequence name) {
        return findDate(name).orElse(null);
    }

    /**
     * Obtain an integer header.
     *
     * @param name The header name
     * @return The date header as a {@link ZonedDateTime} otherwise if it is not present or cannot be parsed null
     */
    default Integer getInt(CharSequence name) {
        return findInt(name).orElse(null);
    }

    /**
     * Find an integer header.
     *
     * @param name The name of the header
     * @return An {@link Optional} of {@link Integer}
     */
    default Optional findInt(CharSequence name) {
        return get(name, ConversionContext.INT);
    }

    /**
     * Get the first value of the given header.
     *
     * @param name The header name
     * @return The first value or null if it is present
     */
    default Optional findFirst(CharSequence name) {
        return getFirst(name, ConversionContext.STRING);
    }

    /**
     * The request or response content type.
     *
     * @return The content type
     */
    default Optional contentType() {
        return getFirst(HttpHeaders.CONTENT_TYPE, MediaType.CONVERSION_CONTEXT);
    }

    /**
     * The request or response content type.
     *
     * @return The content type
     */
    default OptionalLong contentLength() {
        final Long aLong = getFirst(HttpHeaders.CONTENT_LENGTH, ConversionContext.LONG).orElse(null);
        if (aLong != null) {
            return OptionalLong.of(aLong);
        } else {
            return OptionalLong.empty();
        }
    }

    /**
     * A list of accepted {@link MediaType} instances.
     *
     * @return A list of zero or many {@link MediaType} instances
     */
    default List accept() {
        return MediaType.orderedOf(getAll(HttpHeaders.ACCEPT));
    }

    /**
     * The {@code Accept-Charset} header, or {@code null} if unset.
     *
     * @return The {@code Accept-Charset} header
     * @since 4.0.0
     */
    @Nullable
    default Charset acceptCharset() {
        return findAcceptCharset().orElse(null);
    }

    /**
     * The {@code Accept-Charset} header, or empty if unset.
     *
     * @return The {@code Accept-Charset} header
     * @since 4.3.0
     */
    default Optional findAcceptCharset() {
        return findFirst(HttpHeaders.ACCEPT_CHARSET)
            .map(HttpHeadersUtil::parseAcceptCharset);
    }

    /**
     * The {@code Accept-Language} header, or {@code null} if unset.
     *
     * @return The {@code Accept-Language} header
     * @since 4.0.0
     */
    @Nullable
    default Locale acceptLanguage() {
        return findAcceptLanguage().orElse(null);
    }

    /**
     * The {@code Accept-Language} header, or empty if unset.
     *
     * @return The {@code Accept-Language} header
     * @since 4.3.0
     */
    default Optional findAcceptLanguage() {
        return findFirst(HttpHeaders.ACCEPT_LANGUAGE)
            .map(text -> {
                String part = HttpHeadersUtil.splitAcceptHeader(text);
                return part == null ? Locale.getDefault() : Locale.forLanguageTag(part);
            });
    }

    /**
     * @return Whether the {@link HttpHeaders#CONNECTION} header is set to Keep-Alive
     */
    default boolean isKeepAlive() {
        return findFirst(CONNECTION)
                 .map(val -> val.equalsIgnoreCase(HttpHeaderValues.CONNECTION_KEEP_ALIVE)).orElse(false);
    }

    /**
     * @return The {@link #ORIGIN} header
     */
    default Optional getOrigin() {
        return findFirst(ORIGIN);
    }

    /**
     * @return The {@link #AUTHORIZATION} header
     */
    default Optional getAuthorization() {
        return findFirst(AUTHORIZATION);
    }

    /**
     * @return The {@link #CONTENT_TYPE} header
     */
    default Optional getContentType() {
        return findFirst(CONTENT_TYPE);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy