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

com.azure.core.http.HttpHeaders Maven / Gradle / Ivy

There is a newer version: 1.54.1
Show newest version
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.core.http;

import com.azure.core.util.CoreUtils;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * A collection of headers on an HTTP request or response.
 */
public class HttpHeaders implements Iterable {
    // This map is a case-insensitive key (i.e. lower-cased), but the returned HttpHeader key will be as-provided to us
    private final Map headers;

    /**
     * Create an empty HttpHeaders instance.
     */
    public HttpHeaders() {
        headers = new HashMap<>();
    }

    /**
     * Create a HttpHeaders instance with the provided initial headers.
     *
     * @param headers the map of initial headers
     */
    public HttpHeaders(Map headers) {
        this.headers = new HashMap<>(headers.size());
        headers.forEach(this::set);
    }

    /**
     * Create a HttpHeaders instance with the provided initial headers.
     *
     * @param headers the collection of initial headers
     */
    public HttpHeaders(Iterable headers) {
        this.headers = new HashMap<>();
        for (final HttpHeader header : headers) {
            this.set(header.getName(), header.getValuesList());
        }
    }

    HttpHeaders(HttpHeaders headers) {
        this.headers = new HashMap<>((int) (headers.headers.size() / 0.75f));
        headers.headers.forEach((key, value) ->
            this.headers.put(key, new HttpHeader(value.getName(), value.getValuesList())));
    }

    /**
     * Create a HttpHeaders instance with an initial {@code size} empty headers
     *
     * @param initialCapacity the initial capacity of headers map.
     */
    public HttpHeaders(int initialCapacity) {
        this.headers = new HashMap<>(initialCapacity);
    }

    /**
     * Gets the number of headers in the collection.
     *
     * @return the number of headers in this collection.
     */
    public int getSize() {
        return headers.size();
    }

    /**
     * Adds a {@link HttpHeader header} with the given name and value if a header with that name doesn't already exist,
     * otherwise adds the {@code value} to the existing header.
     *
     * @param name The name of the header.
     * @param value The value of the header.
     * @return The updated HttpHeaders object.
     * @deprecated Use {@link #add(HttpHeaderName, String)} as it provides better performance.
     */
    @Deprecated
    public HttpHeaders add(String name, String value) {
        return addInternal(formatKey(name), name, value);
    }

    /**
     * Adds a {@link HttpHeader header} with the given name and value if a header with that name doesn't already exist,
     * otherwise adds the {@code value} to the existing header.
     *
     * @param name The name of the header.
     * @param value The value of the header.
     * @return The updated HttpHeaders object.
     */
    public HttpHeaders add(HttpHeaderName name, String value) {
        return addInternal(name.getCaseInsensitiveName(), name.getCaseSensitiveName(), value);
    }

    private HttpHeaders addInternal(String formattedName, String name, String value) {
        if (name == null || value == null) {
            return this;
        }

        headers.compute(formattedName, (key, header) -> {
            if (header == null) {
                return new HttpHeader(name, value);
            } else {
                header.addValue(value);
                return header;
            }
        });

        return this;
    }

    /**
     * Sets a {@link HttpHeader header} with the given name and value.
     *
     * 

If header with same name already exists then the value will be overwritten.

* * @param name the name * @param value the value * @return The updated HttpHeaders object * @deprecated Use {@link #set(HttpHeaderName, String)} instead. */ @Deprecated public HttpHeaders put(String name, String value) { return set(name, value); } /** * Sets a {@link HttpHeader header} with the given name and value. If a header with same name already exists then * the value will be overwritten. If the given value is null, the header with the given name will be removed. * * @param name the name to set in the header. If it is null, this method will return with no changes to the * headers. * @param value the value * @return The updated HttpHeaders object * @deprecated Use {@link #set(HttpHeaderName, String)} as it provides better performance. */ @Deprecated public HttpHeaders set(String name, String value) { return setInternal(formatKey(name), name, value); } /** * Sets a {@link HttpHeader header} with the given name and value. If a header with same name already exists then * the value will be overwritten. If the given value is null, the header with the given name will be removed. * * @param name the name to set in the header. If it is null, this method will return with no changes to the * headers. * @param value the value * @return The updated HttpHeaders object */ public HttpHeaders set(HttpHeaderName name, String value) { return setInternal(name.getCaseInsensitiveName(), name.getCaseSensitiveName(), value); } private HttpHeaders setInternal(String formattedName, String name, String value) { if (name == null) { return this; } if (value == null) { removeInternal(name); } else { headers.put(formattedName, new HttpHeader(name, value)); } return this; } /** * Sets a {@link HttpHeader header} with the given name and the list of values provided, such that the given values * will be comma-separated when necessary. If a header with same name already exists then the values will be * overwritten. If the given values list is null, the header with the given name will be removed. * * @param name the name * @param values the values that will be comma-separated as appropriate * @return The updated HttpHeaders object * @deprecated Use {@link #set(HttpHeaderName, List)} as it provides better performance. */ @Deprecated public HttpHeaders set(String name, List values) { return setInternal(formatKey(name), name, values); } /** * Sets a {@link HttpHeader header} with the given name and the list of values provided, such that the given values * will be comma-separated when necessary. If a header with same name already exists then the values will be * overwritten. If the given values list is null, the header with the given name will be removed. * * @param name the name * @param values the values that will be comma-separated as appropriate * @return The updated HttpHeaders object */ public HttpHeaders set(HttpHeaderName name, List values) { return setInternal(name.getCaseInsensitiveName(), name.getCaseSensitiveName(), values); } private HttpHeaders setInternal(String formattedName, String name, List values) { if (formattedName == null) { return this; } if (CoreUtils.isNullOrEmpty(values)) { removeInternal(formattedName); } else { headers.put(formattedName, new HttpHeader(name, values)); } return this; } /** * Sets all provided header key/values pairs into this HttpHeaders instance. This is equivalent to calling {@code * headers.forEach(this::set)}, and therefore the behavior is as specified in {@link #set(String, List)}. In other * words, this will create a header for each key in the provided map, replacing or removing an existing one, * depending on the value. If the given values list is null, the header with the given name will be removed. If the * given name is already a header, it will be removed and replaced with the headers provided. *

* Use {@link #setAllHttpHeaders(HttpHeaders)} if you already have an instance of {@link HttpHeaders} as it provides better * performance. * * @param headers a map containing keys representing header names, and keys representing the associated values. * @return The updated HttpHeaders object * @throws NullPointerException If {@code headers} is null. */ public HttpHeaders setAll(Map> headers) { headers.forEach(this::set); return this; } /** * Sets all headers from the passed {@code headers} into this {@link HttpHeaders}. *

* This is the equivalent to calling {@code headers.forEach(header -> set(header.getName(), header.getValuesList())} * and therefore the behavior is as specified in {@link #set(String, List)}. *

* If {@code headers} is null this is a no-op. * * @param headers The headers to add into this {@link HttpHeaders}. * @return The updated HttpHeaders object. */ public HttpHeaders setAllHttpHeaders(HttpHeaders headers) { if (headers != null) { headers.headers.forEach((headerName, header) -> setInternal(headerName, header.getName(), header.getValuesList())); } return this; } /** * Gets the {@link HttpHeader header} for the provided header name. null is returned if the header isn't * found. * * @param name the name of the header to find. * @return the header if found, null otherwise. * @deprecated Use {@link #get(HttpHeaderName)} as it provides better performance. */ @Deprecated public HttpHeader get(String name) { return getInternal(formatKey(name)); } /** * Gets the {@link HttpHeader header} for the provided header name. null is returned if the header isn't * found. * * @param name the name of the header to find. * @return the header if found, null otherwise. */ public HttpHeader get(HttpHeaderName name) { return getInternal(name.getCaseInsensitiveName()); } private HttpHeader getInternal(String formattedName) { return headers.get(formattedName); } /** * Removes the {@link HttpHeader header} with the provided header name. null is returned if the header isn't * found. * * @param name the name of the header to remove. * @return the header if removed, null otherwise. * @deprecated Use {@link #remove(HttpHeaderName)} as it provides better performance. */ @Deprecated public HttpHeader remove(String name) { return removeInternal(formatKey(name)); } /** * Removes the {@link HttpHeader header} with the provided header name. null is returned if the header isn't * found. * * @param name the name of the header to remove. * @return the header if removed, null otherwise. */ public HttpHeader remove(HttpHeaderName name) { return removeInternal(name.getCaseInsensitiveName()); } private HttpHeader removeInternal(String formattedName) { return headers.remove(formattedName); } /** * Get the value for the provided header name. null is returned if the header name isn't found. * * @param name the name of the header whose value is being retrieved. * @return the value of the header, or null if the header isn't found * @deprecated Use {@link #getValue(HttpHeaderName)} as it provides better performance. */ @Deprecated public String getValue(String name) { return getValueInternal(formatKey(name)); } /** * Get the value for the provided header name. null is returned if the header name isn't found. * * @param name the name of the header whose value is being retrieved. * @return the value of the header, or null if the header isn't found */ public String getValue(HttpHeaderName name) { return getValueInternal(name.getCaseInsensitiveName()); } private String getValueInternal(String formattedName) { final HttpHeader header = getInternal(formattedName); return header == null ? null : header.getValue(); } /** * Get the values for the provided header name. null is returned if the header name isn't found. * *

This returns {@link #getValue(String) getValue} split by {@code comma}.

* * @param name the name of the header whose value is being retrieved. * @return the values of the header, or null if the header isn't found * @deprecated Use {@link #getValue(HttpHeaderName)} as it provides better performance. */ @Deprecated public String[] getValues(String name) { return getValuesInternal(formatKey(name)); } /** * Get the values for the provided header name. null is returned if the header name isn't found. * *

This returns {@link #getValue(String) getValue} split by {@code comma}.

* * @param name the name of the header whose value is being retrieved. * @return the values of the header, or null if the header isn't found */ public String[] getValues(HttpHeaderName name) { return getValuesInternal(name.getCaseInsensitiveName()); } private String[] getValuesInternal(String formattedName) { final HttpHeader header = getInternal(formattedName); return header == null ? null : header.getValues(); } /** * Returns a copy of the http headers as an unmodifiable {@link Map} representation of the state of the headers at * the time of the toMap call. This map will not change as the underlying http headers change, and nor will * modifying the key or values contained in the map have any effect on the state of the http headers. * *

Note that there may be performance implications of using Map APIs on the returned Map. It is highly * recommended that users prefer to use alternate APIs present on the HttpHeaders class, over using APIs present on * the returned Map class. For example, use the {@link #get(String)} API, rather than {@code * httpHeaders.toMap().get(name)}.

* * @return the headers in a copied and unmodifiable form. */ public Map toMap() { final Map result = new HashMap<>(); for (final HttpHeader header : headers.values()) { result.put(header.getName(), header.getValue()); } return Collections.unmodifiableMap(result); } /** * Returns a copy of the http headers as an unmodifiable {@link Map} representation of the state of the headers at * the time of the toMultiMap call. This map will not change as the underlying http headers change, and nor will * modifying the key or values contained in the map have any effect on the state of the http headers. * *

Note that there may be performance implications of using Map APIs on the returned Map. It is highly * recommended that users prefer to use alternate APIs present on the HttpHeaders class, over using APIs present on * the returned Map class. For example, use the {@link #get(String)} API, rather than {@code * httpHeaders.toMap().get(name)}.

* * @return the headers in a copied and unmodifiable form. */ Map toMultiMap() { final Map result = new HashMap<>(); for (final HttpHeader header : headers.values()) { result.put(header.getName(), header.getValues()); } return Collections.unmodifiableMap(result); } /** * {@inheritDoc} */ @Override public Iterator iterator() { return headers.values().iterator(); } /** * Get a {@link Stream} representation of the HttpHeader values in this instance. * * @return A {@link Stream} of all header values in this instance. */ public Stream stream() { return headers.values().stream(); } @Override public String toString() { return this.stream() .map(header -> header.getName() + "=" + header.getValue()) .collect(Collectors.joining(", ")); } private static String formatKey(String name) { return (name == null) ? null : name.toLowerCase(Locale.ROOT); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy