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

io.github.stylesmile.server.Headers Maven / Gradle / Ivy

package io.github.stylesmile.server;

import java.io.IOException;
import java.io.OutputStream;
import java.util.*;

import static io.github.stylesmile.server.JdkHTTPServer.CRLF;
import static io.github.stylesmile.server.JdkHTTPServer.parseDate;

/**
 * The {@code Headers} class encapsulates a collection of HTTP headers.
 * 

* Header names are treated case-insensitively, although this class retains * their original case. Header insertion order is maintained as well. */ public class Headers implements Iterable

{ // due to the requirements of case-insensitive name comparisons, // retaining the original case, and retaining header insertion order, // and due to the fact that the number of headers is generally // quite small (usually under 12 headers), we use a simple array with // linear access times, which proves to be more efficient and // straightforward than the alternatives protected Header[] headers = new Header[12]; protected int count; /** * Returns the number of added headers. * * @return the number of added headers */ public int size() { return count; } /** * Returns the value of the first header with the given name. * * @param name the header name (case insensitive) * @return the header value, or null if none exists */ public String get(String name) { for (int i = 0; i < count; i++) if (headers[i].getName().equalsIgnoreCase(name)) return headers[i].getValue(); return null; } /** * Returns the Date value of the header with the given name. * * @param name the header name (case insensitive) * @return the header value as a Date, or null if none exists * or if the value is not in any supported date format */ public Date getDate(String name) { try { String header = get(name); return header == null ? null : parseDate(header); } catch (IllegalArgumentException iae) { return null; } } /** * Returns whether there exists a header with the given name. * * @param name the header name (case insensitive) * @return whether there exists a header with the given name */ public boolean contains(String name) { return get(name) != null; } /** * Adds a header with the given name and value to the end of this * collection of headers. Leading and trailing whitespace are trimmed. * * @param name the header name (case insensitive) * @param value the header value */ public void add(String name, String value) { Header header = new Header(name, value); // also validates // expand array if necessary if (count == headers.length) { Header[] expanded = new Header[2 * count]; System.arraycopy(headers, 0, expanded, 0, count); headers = expanded; } headers[count++] = header; // inlining header would cause a bug! } /** * Adds all given headers to the end of this collection of headers, * in their original order. * * @param headers the headers to add */ public void addAll(Headers headers) { for (Header header : headers) add(header.getName(), header.getValue()); } /** * Adds a header with the given name and value, replacing the first * existing header with the same name. If there is no existing header * with the same name, it is added as in {@link #add}. * * @param name the header name (case insensitive) * @param value the header value * @return the replaced header, or null if none existed */ public Header replace(String name, String value) { for (int i = 0; i < count; i++) { if (headers[i].getName().equalsIgnoreCase(name)) { Header prev = headers[i]; headers[i] = new Header(name, value); return prev; } } add(name, value); return null; } /** * Removes all headers with the given name (if any exist). * * @param name the header name (case insensitive) */ public void remove(String name) { int j = 0; for (int i = 0; i < count; i++) if (!headers[i].getName().equalsIgnoreCase(name)) headers[j++] = headers[i]; while (count > j) headers[--count] = null; } /** * Writes the headers to the given stream (including trailing CRLF). * * @param out the stream to write the headers to * @throws IOException if an error occurs */ public void writeTo(OutputStream out) throws IOException { for (int i = 0; i < count; i++) { out.write(JdkHTTPServer.getBytes(headers[i].getName(), ": ", headers[i].getValue())); out.write(CRLF); } out.write(CRLF); // ends header block } /** * Returns a header's parameters. Parameter order is maintained, * and the first key (in iteration order) is the header's value * without the parameters. * * @param name the header name (case insensitive) * @return the header's parameter names and values */ public Map getParams(String name) { Map params = new LinkedHashMap(); for (String param : JdkHTTPServer.split(get(name), ";", -1)) { String[] pair = JdkHTTPServer.split(param, "=", 2); String val = pair.length == 1 ? "" : JdkHTTPServer.trimLeft(JdkHTTPServer.trimRight(pair[1], '"'), '"'); params.put(pair[0], val); } return params; } /** * Returns an iterator over the headers, in their insertion order. * If the headers collection is modified during iteration, the * iteration result is undefined. The remove operation is unsupported. * * @return an Iterator over the headers */ public Iterator
iterator() { // we use the built-in wrapper instead of a trivial custom implementation // since even a tiny anonymous class here compiles to a 1.5K class file return Arrays.asList(headers).subList(0, count).iterator(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy