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

io.helidon.http.Headers Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2023 Oracle and/or its affiliates.
 *
 * 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 io.helidon.http;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import io.helidon.common.media.type.MediaType;

/**
 * View of HTTP Headers.
 * This API is designed to support both HTTP/1 and HTTP/2.
 * Note that HTTP/2 has all headers lower case (mandatory), while HTTP/1 headers are compared ignoring
 * case.
 * When you configure headers to be sent using HTTP/2, all names will be lowercase.
 * When you configure headers to be sent using HTTP/1, names will be sent as configured.
 * When you receive headers, the stored values (as can be obtained by {@link Header#name()})
 * will be as sent on the transport. These value will be available using any cased names (though performance may be worse
 * if uppercase letters are used to obtain HTTP/2 headers).
 */
public interface Headers extends Iterable
{ /** * Get all values of a header. * * @param name name of the header * @param defaultSupplier supplier to obtain default values if the header is not present * @return list of header values */ List all(HeaderName name, Supplier> defaultSupplier); /** * Whether these headers contain a header with the provided name. * * @param name header name * @return {@code true} if the header is defined */ boolean contains(HeaderName name); /** * Whether these headers contain a header with the provided name and value. * * @param value value of the header * @return {@code true} if the header is defined */ boolean contains(Header value); /** * Get a header value. * * @param name name of the header * @return value if present * @throws java.util.NoSuchElementException in case the header is not present */ Header get(HeaderName name); /** * Returns a header value as a single {@link String} potentially concatenated using comma character * from {@link #all(HeaderName, java.util.function.Supplier)} header fields. *

* According to RFC2616, Message Headers: *

* Multiple message-header fields with the same field-name MAY be * present in a message if and only if the entire field-value for that * header field is defined as a comma-separated list [i.e., #(values)]. * It MUST be possible to combine the multiple header fields into one * "field-name: field-value" pair, without changing the semantics of the * message, by appending each subsequent field-value to the first, each * separated by a comma. *
* * @param headerName the header name * @return all header values concatenated using comma separator * @throws NullPointerException if {@code headerName} is {@code null} * @see #all(HeaderName, java.util.function.Supplier) * @see #values(HeaderName) */ default Optional value(HeaderName headerName) { if (contains(headerName)) { List hdrs = all(headerName, List::of); return Optional.of(String.join(",", hdrs)); } return Optional.empty(); } /** * Returns a first header value. * * @param headerName the header name * @return the first value * @throws NullPointerException if {@code headerName} is {@code null} */ default Optional first(HeaderName headerName) { if (contains(headerName)) { return Optional.of(get(headerName).get()); } return Optional.empty(); } /** * Returns an unmodifiable {@link java.util.List} of all comma separated header value parts - Such segmentation is NOT * valid for * all header semantics, however it is very common. Refer to actual header semantics standard/description before use. *

* Result is composed from all header fields with requested {@code headerName} where each header value is tokenized by * a comma character. Tokenization respects value quoting by double-quote character. *

* Always returns a List, which may be empty if the header is not present. * * @param headerName the header name * @return a {@code List} of values with zero or greater size, never {@code null} * @throws NullPointerException if {@code headerName} is {@code null} * @see #all(HeaderName, java.util.function.Supplier) * @see #value(HeaderName) */ default List values(HeaderName headerName) { return all(headerName, List::of) .stream() .flatMap(val -> Utils.tokenize(',', "\"", true, val).stream()) .collect(Collectors.toList()); } /** * Content length if defined. * * @return content length or empty if not defined * @see HeaderNames#CONTENT_LENGTH */ default OptionalLong contentLength() { if (contains(HeaderNameEnum.CONTENT_LENGTH)) { return OptionalLong.of(get(HeaderNameEnum.CONTENT_LENGTH).get(long.class)); } return OptionalLong.empty(); } /** * Content type (if defined). * * @return content type, empty if content type is not present * @see HeaderNames#CONTENT_TYPE */ default Optional contentType() { if (contains(HeaderNameEnum.CONTENT_TYPE)) { return Optional.of(HttpMediaType.create(get(HeaderNameEnum.CONTENT_TYPE) .get())); } return Optional.empty(); } /** * Number of headers in these headers. * * @return size of these headers */ int size(); /** * Returns a list of acceptedTypes ({@link HeaderNames#ACCEPT} header) content discoveryTypes in * quality factor order. Never {@code null}. * Returns an empty list by default. * * @return A list of acceptedTypes media discoveryTypes. */ List acceptedTypes(); /** * Whether this media type is accepted by these headers. * As this method is useful only for server request headers, it returns {@code true } by default. * * @param mediaType media type to test * @return {@code true} if this media type would be accepted */ default boolean isAccepted(MediaType mediaType) { return true; } /** * Creates a multivalued map from these headers. * This is extremely inefficient and should not be used. * * @return map of headers * @deprecated use other methods to handle headers, preferably using pull approach */ @Deprecated default Map> toMap() { Map> headers = new HashMap<>(); forEach(it -> headers.put(it.name(), it.allValues())); return headers; } /** * A sequential stream with these headers as the source. * * @return stream of header values */ default Stream

stream() { return StreamSupport.stream(spliterator(), false); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy