io.muserver.Headers Maven / Gradle / Ivy
Show all versions of mu-server Show documentation
package io.muserver;
import io.netty.handler.codec.HeadersUtils;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpHeaders;
import javax.ws.rs.core.MediaType;
import java.util.*;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
import static java.util.Collections.emptyList;
public class Headers implements Iterable> {
private final HttpHeaders entries;
public Headers() {
this(new DefaultHttpHeaders());
}
Headers(HttpHeaders entries) {
this.entries = entries;
}
public String get(String name) {
return entries.get(name);
}
public String get(CharSequence name) {
return entries.get(name);
}
public String get(CharSequence name, String defaultValue) {
return entries.get(name, defaultValue);
}
public Integer getInt(CharSequence name) {
return entries.getInt(name);
}
public int getInt(CharSequence name, int defaultValue) {
return entries.getInt(name, defaultValue);
}
public Short getShort(CharSequence name) {
return entries.getShort(name);
}
public short getShort(CharSequence name, short defaultValue) {
return entries.getShort(name, defaultValue);
}
public Long getTimeMillis(CharSequence name) {
return entries.getTimeMillis(name);
}
public long getTimeMillis(CharSequence name, long defaultValue) {
return entries.getTimeMillis(name, defaultValue);
}
public List getAll(String name) {
return entries.getAll(name);
}
public List getAll(CharSequence name) {
return entries.getAll(name);
}
public List> entries() {
return entries.entries();
}
public boolean contains(String name) {
return entries.contains(name);
}
public Iterator> iterator() {
return entries.iteratorAsString();
}
public Iterator> iteratorCharSequence() {
return entries.iteratorCharSequence();
}
public boolean contains(CharSequence name) {
return entries.contains(name);
}
public boolean isEmpty() {
return entries.isEmpty();
}
public int size() {
return entries.size();
}
public Set names() {
return entries.names();
}
public Headers add(String name, Object value) {
entries.add(name, value);
return this;
}
public Headers add(CharSequence name, Object value) {
entries.add(name, value);
return this;
}
public Headers add(String name, Iterable values) {
entries.add(name, values);
return this;
}
public Headers add(CharSequence name, Iterable values) {
entries.add(name, values);
return this;
}
public Headers add(Headers headers) {
for (Map.Entry e : headers) {
add(e.getKey(), e.getValue());
}
return this;
}
public Headers addInt(CharSequence name, int value) {
entries.addInt(name, value);
return this;
}
public Headers addShort(CharSequence name, short value) {
entries.addShort(name, value);
return this;
}
public Headers set(String name, Object value) {
entries.set(name, value);
return this;
}
public Headers set(CharSequence name, Object value) {
entries.set(name, value);
return this;
}
public Headers set(String name, Iterable values) {
entries.set(name, values);
return this;
}
public Headers set(CharSequence name, Iterable values) {
entries.set(name, values);
return this;
}
public Headers set(Headers headers) {
checkNotNull(headers, "headers");
clear();
for (Map.Entry entry : headers) {
add(entry.getKey(), entry.getValue());
}
return this;
}
public Headers setAll(Headers headers) {
checkNotNull(headers, "headers");
for (String name : headers.names()) {
set(name, headers.getAll(name));
}
return this;
}
public Headers setInt(CharSequence name, int value) {
entries.setInt(name, value);
return this;
}
public Headers setShort(CharSequence name, short value) {
entries.setShort(name, value);
return this;
}
public Headers remove(String name) {
entries.remove(name);
return this;
}
public Headers remove(CharSequence name) {
entries.remove(name);
return this;
}
public Headers clear() {
entries.clear();
return this;
}
public boolean contains(String name, String value, boolean ignoreCase) {
return entries.contains(name, value, ignoreCase);
}
public boolean containsValue(CharSequence name, CharSequence value, boolean ignoreCase) {
return entries.containsValue(name, value, ignoreCase);
}
public String getAsString(CharSequence name) {
return entries.getAsString(name);
}
public List getAllAsString(CharSequence name) {
return entries.getAllAsString(name);
}
public Iterator> iteratorAsString() {
return entries.iteratorAsString();
}
public boolean contains(CharSequence name, CharSequence value, boolean ignoreCase) {
return entries.contains(name, value, ignoreCase);
}
public boolean equals(Object o) {
return entries.equals(o);
}
public int hashCode() {
return entries.hashCode();
}
public String toString() {
return HeadersUtils.toString(getClass(), iteratorCharSequence(), size());
}
HttpHeaders nettyHeaders() {
return entries;
}
/**
* Returns true if the headers suggest there is a message body by checking if there is a {@link HeaderNames#TRANSFER_ENCODING}
* header or the {@link HeaderNames#CONTENT_LENGTH} is greater than 0.
*
* @return True if there should be a body; otherwise false;
*/
public boolean hasBody() {
return contains(HeaderNames.TRANSFER_ENCODING) || getInt(HeaderNames.CONTENT_LENGTH, -1) > 0;
}
/**
* Gets the Accept-Charset
header value.
* For example, if a client sends text/html,application/xml;q=0.9
* then this would return a list of two values: text/html, and application/xml where application/xml
* has a parameter q
of value 0.9
*
* @return Returns a parsed Accept
header, or an empty list if none specified.
*/
public List accept() {
return getParameterizedHeaderWithValues(HeaderNames.ACCEPT);
}
/**
* Gets the Accept
header value.
* For example, if a client sends iso-8859-5, unicode-1-1;q=0.8
* then this would return a list of two values: iso-8859-5, and unicode-1-1 where unicode-1-1
* has a parameter q
of value 0.8
*
* @return Returns a parsed Accept-Charset
header, or an empty list if none specified.
*/
public List acceptCharset() {
return getParameterizedHeaderWithValues(HeaderNames.ACCEPT_CHARSET);
}
/**
* Gets the Accept-Encoding
header value.
* For example, if a client sends gzip, deflate
* then this would return a list of two values: gzip and deflate
*
* @return Returns a parsed Accept-Encoding
header, or an empty list if none specified.
*/
public List acceptEncoding() {
return getParameterizedHeaderWithValues(HeaderNames.ACCEPT_ENCODING);
}
/**
* Gets the Forwarded
header value.
* For example, if a client sends for=192.0.2.60;proto=http;by=203.0.113.43
* then this would return a list of length one that has for, proto, and by values.
* If there is no Forwarded header, however there are X-Forwarded-* headers, then those
* will be used to generate pseudo-forwarded headers.
*
* @return Returns a parsed Forwarded
header, or an empty list if none specified.
*/
public List forwarded() {
List all = getAll(HeaderNames.FORWARDED);
if (all.isEmpty()) {
List hosts = getAll(HeaderNames.X_FORWARDED_HOST);
List ports = getAll(HeaderNames.X_FORWARDED_PORT);
List protos = getAll(HeaderNames.X_FORWARDED_PROTO);
List fors = getAll(HeaderNames.X_FORWARDED_FOR);
int max = Math.max(Math.max(Math.max(hosts.size(), protos.size()), fors.size()), ports.size());
if (max == 0) {
return emptyList();
}
List results = new ArrayList<>();
boolean includeHost = hosts.size() == max;
boolean includeProto = protos.size() == max;
boolean includeFor = fors.size() == max;
boolean includePort = ports.size() == max;
String curHost = includePort && !includeHost ? get(HeaderNames.HOST) : null;
for (int i = 0; i < max; i++) {
String host = includeHost ? hosts.get(i) : null;
String port = includePort ? ports.get(i) : null;
String proto = includeProto ? protos.get(i) : null;
String forValue = includeFor ? fors.get(i) : null;
boolean useDefaultPort = port == null || (proto != null &&
((proto.equalsIgnoreCase("http") && "80".equals(port))
|| proto.equalsIgnoreCase("https") && "443".equals(port)));
String hostToUse =
includeHost ? host
: includePort ? curHost
: null;
if (hostToUse != null && !useDefaultPort) {
hostToUse = hostToUse.replaceFirst(":[0-9]+$", "") + ":" + port;
}
results.add(new ForwardedHeader(null, forValue, hostToUse, proto, null));
}
return results;
} else {
List results = new ArrayList<>();
for (String s : all) {
results.addAll(ForwardedHeader.fromString(s));
}
return results;
}
}
/**
* Gets the Accept-Language
header value.
* For example, if a client sends en-US,en;q=0.5
* then this would return a list of two values: en-US and en where en has a q
value of 0.5
*
* @return Returns a parsed Accept-Language
header, or an empty list if none specified.
*/
public List acceptLanguage() {
return getParameterizedHeaderWithValues(HeaderNames.ACCEPT_LANGUAGE);
}
private List getParameterizedHeaderWithValues(CharSequence headerName) {
String input = get(headerName);
if (input == null) {
return emptyList();
}
return ParameterizedHeaderWithValue.fromString(input);
}
/**
* Gets the Cache-Control
header value.
*
* @return A map of cache control directives to their optional values. If no cache-control
* is in the header, then the resulting map will be empty.
*/
public ParameterizedHeader cacheControl() {
return ParameterizedHeader.fromString(get(HeaderNames.CACHE_CONTROL));
}
/**
* Gets the parsed Content-Type
header value.
*
* @return The media type of the content specified by the headers.
*/
public MediaType contentType() {
String value = get(HeaderNames.CONTENT_TYPE);
if (value == null) {
return null;
}
return MediaTypeParser.fromString(value);
}
}