/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2014 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * 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.undertow.util;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URLDecoder;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

NOTE: if you add a new header here you must also add it to HttpRequestParser
Author:David M. Lloyd
/** * NOTE: if you add a new header here you must also add it to {@link io.undertow.server.protocol.http.HttpRequestParser} * * @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a> */
public final class Headers { private Headers() { } // Headers as strings public static final String ACCEPT_STRING = "Accept"; public static final String ACCEPT_CHARSET_STRING = "Accept-Charset"; public static final String ACCEPT_ENCODING_STRING = "Accept-Encoding"; public static final String ACCEPT_LANGUAGE_STRING = "Accept-Language"; public static final String ACCEPT_RANGES_STRING = "Accept-Ranges"; public static final String AGE_STRING = "Age"; public static final String ALLOW_STRING = "Allow"; public static final String AUTHENTICATION_INFO_STRING = "Authentication-Info"; public static final String AUTHORIZATION_STRING = "Authorization"; public static final String CACHE_CONTROL_STRING = "Cache-Control"; public static final String COOKIE_STRING = "Cookie"; public static final String COOKIE2_STRING = "Cookie2"; public static final String CONNECTION_STRING = "Connection"; public static final String CONTENT_DISPOSITION_STRING = "Content-Disposition"; public static final String CONTENT_ENCODING_STRING = "Content-Encoding"; public static final String CONTENT_LANGUAGE_STRING = "Content-Language"; public static final String CONTENT_LENGTH_STRING = "Content-Length"; public static final String CONTENT_LOCATION_STRING = "Content-Location"; public static final String CONTENT_MD5_STRING = "Content-MD5"; public static final String CONTENT_RANGE_STRING = "Content-Range"; public static final String CONTENT_SECURITY_POLICY_STRING = "Content-Security-Policy"; public static final String CONTENT_TYPE_STRING = "Content-Type"; public static final String DATE_STRING = "Date"; public static final String ETAG_STRING = "ETag"; public static final String EXPECT_STRING = "Expect"; public static final String EXPIRES_STRING = "Expires"; public static final String FORWARDED_STRING = "Forwarded"; public static final String FROM_STRING = "From"; public static final String HOST_STRING = "Host"; public static final String IF_MATCH_STRING = "If-Match"; public static final String IF_MODIFIED_SINCE_STRING = "If-Modified-Since"; public static final String IF_NONE_MATCH_STRING = "If-None-Match"; public static final String IF_RANGE_STRING = "If-Range"; public static final String IF_UNMODIFIED_SINCE_STRING = "If-Unmodified-Since"; public static final String LAST_MODIFIED_STRING = "Last-Modified"; public static final String LOCATION_STRING = "Location"; public static final String MAX_FORWARDS_STRING = "Max-Forwards"; public static final String ORIGIN_STRING = "Origin"; public static final String PRAGMA_STRING = "Pragma"; public static final String PROXY_AUTHENTICATE_STRING = "Proxy-Authenticate"; public static final String PROXY_AUTHORIZATION_STRING = "Proxy-Authorization"; public static final String RANGE_STRING = "Range"; public static final String REFERER_STRING = "Referer"; public static final String REFERRER_POLICY_STRING = "Referrer-Policy"; public static final String REFRESH_STRING = "Refresh"; public static final String RETRY_AFTER_STRING = "Retry-After"; public static final String SEC_WEB_SOCKET_ACCEPT_STRING = "Sec-WebSocket-Accept"; public static final String SEC_WEB_SOCKET_EXTENSIONS_STRING = "Sec-WebSocket-Extensions"; public static final String SEC_WEB_SOCKET_KEY_STRING = "Sec-WebSocket-Key"; public static final String SEC_WEB_SOCKET_KEY1_STRING = "Sec-WebSocket-Key1"; public static final String SEC_WEB_SOCKET_KEY2_STRING = "Sec-WebSocket-Key2"; public static final String SEC_WEB_SOCKET_LOCATION_STRING = "Sec-WebSocket-Location"; public static final String SEC_WEB_SOCKET_ORIGIN_STRING = "Sec-WebSocket-Origin"; public static final String SEC_WEB_SOCKET_PROTOCOL_STRING = "Sec-WebSocket-Protocol"; public static final String SEC_WEB_SOCKET_VERSION_STRING = "Sec-WebSocket-Version"; public static final String SERVER_STRING = "Server"; public static final String SERVLET_ENGINE_STRING = "Servlet-Engine"; public static final String SET_COOKIE_STRING = "Set-Cookie"; public static final String SET_COOKIE2_STRING = "Set-Cookie2"; public static final String SSL_CLIENT_CERT_STRING = "SSL_CLIENT_CERT"; public static final String SSL_CIPHER_STRING = "SSL_CIPHER"; public static final String SSL_SESSION_ID_STRING = "SSL_SESSION_ID"; public static final String SSL_CIPHER_USEKEYSIZE_STRING = "SSL_CIPHER_USEKEYSIZE"; public static final String STATUS_STRING = "Status"; public static final String STRICT_TRANSPORT_SECURITY_STRING = "Strict-Transport-Security"; public static final String TE_STRING = "TE"; public static final String TRAILER_STRING = "Trailer"; public static final String TRANSFER_ENCODING_STRING = "Transfer-Encoding"; public static final String UPGRADE_STRING = "Upgrade"; public static final String USER_AGENT_STRING = "User-Agent"; public static final String VARY_STRING = "Vary"; public static final String VIA_STRING = "Via"; public static final String WARNING_STRING = "Warning"; public static final String WWW_AUTHENTICATE_STRING = "WWW-Authenticate"; public static final String X_CONTENT_TYPE_OPTIONS_STRING = "X-Content-Type-Options"; public static final String X_DISABLE_PUSH_STRING = "X-Disable-Push"; public static final String X_FORWARDED_FOR_STRING = "X-Forwarded-For"; public static final String X_FORWARDED_PROTO_STRING = "X-Forwarded-Proto"; public static final String X_FORWARDED_HOST_STRING = "X-Forwarded-Host"; public static final String X_FORWARDED_PORT_STRING = "X-Forwarded-Port"; public static final String X_FORWARDED_SERVER_STRING = "X-Forwarded-Server"; public static final String X_FRAME_OPTIONS_STRING = "X-Frame-Options"; public static final String X_XSS_PROTECTION_STRING = "X-Xss-Protection"; // Header names public static final HttpString ACCEPT = new HttpString(ACCEPT_STRING, 1); public static final HttpString ACCEPT_CHARSET = new HttpString(ACCEPT_CHARSET_STRING, 2); public static final HttpString ACCEPT_ENCODING = new HttpString(ACCEPT_ENCODING_STRING, 3); public static final HttpString ACCEPT_LANGUAGE = new HttpString(ACCEPT_LANGUAGE_STRING, 4); public static final HttpString ACCEPT_RANGES = new HttpString(ACCEPT_RANGES_STRING, 5); public static final HttpString AGE = new HttpString(AGE_STRING, 6); public static final HttpString ALLOW = new HttpString(ALLOW_STRING, 7); public static final HttpString AUTHENTICATION_INFO = new HttpString(AUTHENTICATION_INFO_STRING, 8); public static final HttpString AUTHORIZATION = new HttpString(AUTHORIZATION_STRING, 9); public static final HttpString CACHE_CONTROL = new HttpString(CACHE_CONTROL_STRING, 10); public static final HttpString CONNECTION = new HttpString(CONNECTION_STRING, 11); public static final HttpString CONTENT_DISPOSITION = new HttpString(CONTENT_DISPOSITION_STRING, 12); public static final HttpString CONTENT_ENCODING = new HttpString(CONTENT_ENCODING_STRING, 13); public static final HttpString CONTENT_LANGUAGE = new HttpString(CONTENT_LANGUAGE_STRING, 14); public static final HttpString CONTENT_LENGTH = new HttpString(CONTENT_LENGTH_STRING, 15); public static final HttpString CONTENT_LOCATION = new HttpString(CONTENT_LOCATION_STRING, 16); public static final HttpString CONTENT_MD5 = new HttpString(CONTENT_MD5_STRING, 17); public static final HttpString CONTENT_RANGE = new HttpString(CONTENT_RANGE_STRING, 18); public static final HttpString CONTENT_SECURITY_POLICY = new HttpString(CONTENT_SECURITY_POLICY_STRING, 19); public static final HttpString CONTENT_TYPE = new HttpString(CONTENT_TYPE_STRING, 20); public static final HttpString COOKIE = new HttpString(COOKIE_STRING, 21); public static final HttpString COOKIE2 = new HttpString(COOKIE2_STRING, 22); public static final HttpString DATE = new HttpString(DATE_STRING, 23); public static final HttpString ETAG = new HttpString(ETAG_STRING, 24); public static final HttpString EXPECT = new HttpString(EXPECT_STRING, 25); public static final HttpString EXPIRES = new HttpString(EXPIRES_STRING, 26); public static final HttpString FORWARDED = new HttpString(FORWARDED_STRING, 27); public static final HttpString FROM = new HttpString(FROM_STRING, 28); public static final HttpString HOST = new HttpString(HOST_STRING, 29); public static final HttpString IF_MATCH = new HttpString(IF_MATCH_STRING, 30); public static final HttpString IF_MODIFIED_SINCE = new HttpString(IF_MODIFIED_SINCE_STRING, 31); public static final HttpString IF_NONE_MATCH = new HttpString(IF_NONE_MATCH_STRING, 32); public static final HttpString IF_RANGE = new HttpString(IF_RANGE_STRING, 33); public static final HttpString IF_UNMODIFIED_SINCE = new HttpString(IF_UNMODIFIED_SINCE_STRING, 34); public static final HttpString LAST_MODIFIED = new HttpString(LAST_MODIFIED_STRING, 35); public static final HttpString LOCATION = new HttpString(LOCATION_STRING, 36); public static final HttpString MAX_FORWARDS = new HttpString(MAX_FORWARDS_STRING, 37); public static final HttpString ORIGIN = new HttpString(ORIGIN_STRING, 38); public static final HttpString PRAGMA = new HttpString(PRAGMA_STRING, 39); public static final HttpString PROXY_AUTHENTICATE = new HttpString(PROXY_AUTHENTICATE_STRING, 40); public static final HttpString PROXY_AUTHORIZATION = new HttpString(PROXY_AUTHORIZATION_STRING, 41); public static final HttpString RANGE = new HttpString(RANGE_STRING, 42); public static final HttpString REFERER = new HttpString(REFERER_STRING, 43); public static final HttpString REFERRER_POLICY = new HttpString(REFERRER_POLICY_STRING, 44); public static final HttpString REFRESH = new HttpString(REFRESH_STRING, 45); public static final HttpString RETRY_AFTER = new HttpString(RETRY_AFTER_STRING, 46); public static final HttpString SEC_WEB_SOCKET_ACCEPT = new HttpString(SEC_WEB_SOCKET_ACCEPT_STRING, 47); public static final HttpString SEC_WEB_SOCKET_EXTENSIONS = new HttpString(SEC_WEB_SOCKET_EXTENSIONS_STRING, 48); public static final HttpString SEC_WEB_SOCKET_KEY = new HttpString(SEC_WEB_SOCKET_KEY_STRING, 49); public static final HttpString SEC_WEB_SOCKET_KEY1 = new HttpString(SEC_WEB_SOCKET_KEY1_STRING, 50); public static final HttpString SEC_WEB_SOCKET_KEY2 = new HttpString(SEC_WEB_SOCKET_KEY2_STRING, 51); public static final HttpString SEC_WEB_SOCKET_LOCATION = new HttpString(SEC_WEB_SOCKET_LOCATION_STRING, 52); public static final HttpString SEC_WEB_SOCKET_ORIGIN = new HttpString(SEC_WEB_SOCKET_ORIGIN_STRING, 53); public static final HttpString SEC_WEB_SOCKET_PROTOCOL = new HttpString(SEC_WEB_SOCKET_PROTOCOL_STRING, 54); public static final HttpString SEC_WEB_SOCKET_VERSION = new HttpString(SEC_WEB_SOCKET_VERSION_STRING, 55); public static final HttpString SERVER = new HttpString(SERVER_STRING, 56); public static final HttpString SERVLET_ENGINE = new HttpString(SERVLET_ENGINE_STRING, 57); public static final HttpString SET_COOKIE = new HttpString(SET_COOKIE_STRING, 58); public static final HttpString SET_COOKIE2 = new HttpString(SET_COOKIE2_STRING, 59); public static final HttpString SSL_CIPHER = new HttpString(SSL_CIPHER_STRING, 60); public static final HttpString SSL_CIPHER_USEKEYSIZE = new HttpString(SSL_CIPHER_USEKEYSIZE_STRING, 61); public static final HttpString SSL_CLIENT_CERT = new HttpString(SSL_CLIENT_CERT_STRING, 62); public static final HttpString SSL_SESSION_ID = new HttpString(SSL_SESSION_ID_STRING, 63); public static final HttpString STATUS = new HttpString(STATUS_STRING, 64); public static final HttpString STRICT_TRANSPORT_SECURITY = new HttpString(STRICT_TRANSPORT_SECURITY_STRING, 65); public static final HttpString TE = new HttpString(TE_STRING, 66); public static final HttpString TRAILER = new HttpString(TRAILER_STRING, 67); public static final HttpString TRANSFER_ENCODING = new HttpString(TRANSFER_ENCODING_STRING, 68); public static final HttpString UPGRADE = new HttpString(UPGRADE_STRING, 69); public static final HttpString USER_AGENT = new HttpString(USER_AGENT_STRING, 70); public static final HttpString VARY = new HttpString(VARY_STRING, 71); public static final HttpString VIA = new HttpString(VIA_STRING, 72); public static final HttpString WARNING = new HttpString(WARNING_STRING, 73); public static final HttpString WWW_AUTHENTICATE = new HttpString(WWW_AUTHENTICATE_STRING, 74); public static final HttpString X_CONTENT_TYPE_OPTIONS = new HttpString(X_CONTENT_TYPE_OPTIONS_STRING, 75); public static final HttpString X_DISABLE_PUSH = new HttpString(X_DISABLE_PUSH_STRING, 76); public static final HttpString X_FORWARDED_FOR = new HttpString(X_FORWARDED_FOR_STRING, 77); public static final HttpString X_FORWARDED_HOST = new HttpString(X_FORWARDED_HOST_STRING, 78); public static final HttpString X_FORWARDED_PORT = new HttpString(X_FORWARDED_PORT_STRING, 79); public static final HttpString X_FORWARDED_PROTO = new HttpString(X_FORWARDED_PROTO_STRING, 80); public static final HttpString X_FORWARDED_SERVER = new HttpString(X_FORWARDED_SERVER_STRING, 81); public static final HttpString X_FRAME_OPTIONS = new HttpString(X_FRAME_OPTIONS_STRING, 82); public static final HttpString X_XSS_PROTECTION = new HttpString(X_XSS_PROTECTION_STRING, 83); // Content codings public static final HttpString COMPRESS = new HttpString("compress"); public static final HttpString X_COMPRESS = new HttpString("x-compress"); public static final HttpString DEFLATE = new HttpString("deflate"); public static final HttpString IDENTITY = new HttpString("identity"); public static final HttpString GZIP = new HttpString("gzip"); public static final HttpString X_GZIP = new HttpString("x-gzip"); // Transfer codings public static final HttpString CHUNKED = new HttpString("chunked"); // IDENTITY // GZIP // COMPRESS // DEFLATE // Connection values public static final HttpString KEEP_ALIVE = new HttpString("keep-alive"); public static final HttpString CLOSE = new HttpString("close"); //MIME header used in multipart file uploads public static final String CONTENT_TRANSFER_ENCODING_STRING = "Content-Transfer-Encoding"; public static final HttpString CONTENT_TRANSFER_ENCODING = new HttpString(CONTENT_TRANSFER_ENCODING_STRING); // Authentication Schemes public static final HttpString BASIC = new HttpString("Basic"); public static final HttpString DIGEST = new HttpString("Digest"); public static final HttpString NEGOTIATE = new HttpString("Negotiate"); // Digest authentication Token Names public static final HttpString ALGORITHM = new HttpString("algorithm"); public static final HttpString AUTH_PARAM = new HttpString("auth-param"); public static final HttpString CNONCE = new HttpString("cnonce"); public static final HttpString DOMAIN = new HttpString("domain"); public static final HttpString NEXT_NONCE = new HttpString("nextnonce"); public static final HttpString NONCE = new HttpString("nonce"); public static final HttpString NONCE_COUNT = new HttpString("nc"); public static final HttpString OPAQUE = new HttpString("opaque"); public static final HttpString QOP = new HttpString("qop"); public static final HttpString REALM = new HttpString("realm"); public static final HttpString RESPONSE = new HttpString("response"); public static final HttpString RESPONSE_AUTH = new HttpString("rspauth"); public static final HttpString STALE = new HttpString("stale"); public static final HttpString URI = new HttpString("uri"); public static final HttpString USERNAME = new HttpString("username"); private static final Map<String, HttpString> HTTP_STRING_MAP; static { Map<String, HttpString> map = AccessController.doPrivileged(new PrivilegedAction<Map<String, HttpString>>() { @Override public Map<String, HttpString> run() { Map<String, HttpString> map = new HashMap<>(); Field[] fields = Headers.class.getDeclaredFields(); for(Field field : fields) { if(Modifier.isStatic(field.getModifiers()) && field.getType() == HttpString.class) { field.setAccessible(true); try { HttpString result = (HttpString) field.get(null); map.put(result.toString(), result); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } } return map; } }); HTTP_STRING_MAP = Collections.unmodifiableMap(map); } public static HttpString fromCache(String string) { return HTTP_STRING_MAP.get(string); }
Extracts a token from a header that has a given key. For instance if the header is

content-type=multipart/form-data boundary=myboundary and the key is boundary the myboundary will be returned.

Params:
  • header – The header
  • key – The key that identifies the token to extract
Returns:The token, or null if it was not found
/** * Extracts a token from a header that has a given key. For instance if the header is * <p> * content-type=multipart/form-data boundary=myboundary * and the key is boundary the myboundary will be returned. * * @param header The header * @param key The key that identifies the token to extract * @return The token, or null if it was not found */
@Deprecated public static String extractTokenFromHeader(final String header, final String key) { int pos = header.indexOf(' ' + key + '='); if (pos == -1) { if(!header.startsWith(key + '=')) { return null; } pos = 0; } else { pos++; } int end; int start = pos + key.length() + 1; for (end = start; end < header.length(); ++end) { char c = header.charAt(end); if (c == ' ' || c == '\t' || c == ';') { break; } } return header.substring(start, end); }
Extracts a quoted value from a header that has a given key. For instance if the header is

content-disposition=form-data; name="my field" and the key is name then "my field" will be returned without the quotes.

Params:
  • header – The header
  • key – The key that identifies the token to extract
Returns:The token, or null if it was not found
/** * Extracts a quoted value from a header that has a given key. For instance if the header is * <p> * content-disposition=form-data; name="my field" * and the key is name then "my field" will be returned without the quotes. * * * @param header The header * @param key The key that identifies the token to extract * @return The token, or null if it was not found */
public static String extractQuotedValueFromHeader(final String header, final String key) { int keypos = 0; int pos = -1; boolean whiteSpace = true; boolean inQuotes = false; for (int i = 0; i < header.length() - 1; ++i) { //-1 because we need room for the = at the end //TODO: a more efficient matching algorithm char c = header.charAt(i); if (inQuotes) { if (c == '"') { inQuotes = false; } } else { if (key.charAt(keypos) == c && (whiteSpace || keypos > 0)) { keypos++; whiteSpace = false; } else if (c == '"') { keypos = 0; inQuotes = true; whiteSpace = false; } else { keypos = 0; whiteSpace = c == ' ' || c == ';' || c == '\t'; } if (keypos == key.length()) { if (header.charAt(i + 1) == '=') { pos = i + 2; break; } else { keypos = 0; } } } } if (pos == -1) { return null; } int end; int start = pos; if (header.charAt(start) == '"') { start++; for (end = start; end < header.length(); ++end) { char c = header.charAt(end); if (c == '"') { break; } } return header.substring(start, end); } else { //no quotes for (end = start; end < header.length(); ++end) { char c = header.charAt(end); if (c == ' ' || c == '\t' || c == ';') { break; } } return header.substring(start, end); } }
Extracts a quoted value from a header that has a given key. For instance if the header is

content-disposition=form-data; filename*="utf-8''test.txt" and the key is filename* then "test.txt" will be returned after extracting character set and language (following RFC 2231) and performing URL decoding to the value using the specified encoding

Params:
  • header – The header
  • key – The key that identifies the token to extract
Returns:The token, or null if it was not found
/** * Extracts a quoted value from a header that has a given key. For instance if the header is * <p> * content-disposition=form-data; filename*="utf-8''test.txt" * and the key is filename* then "test.txt" will be returned after extracting character set and language * (following RFC 2231) and performing URL decoding to the value using the specified encoding * * @param header The header * @param key The key that identifies the token to extract * @return The token, or null if it was not found */
public static String extractQuotedValueFromHeaderWithEncoding(final String header, final String key) { String value = extractQuotedValueFromHeader(header, key); if (value != null) { return value; } value = extractQuotedValueFromHeader(header , key + "*"); if(value != null) { int characterSetDelimiter = value.indexOf('\''); int languageDelimiter = value.lastIndexOf('\'', characterSetDelimiter + 1); String characterSet = value.substring(0, characterSetDelimiter); try { String fileNameURLEncoded = value.substring(languageDelimiter + 1); return URLDecoder.decode(fileNameURLEncoded, characterSet); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } return null; } }