bool HTTPHeaderMap::remove(const String& name) { HTTPHeaderName headerName; if (findHTTPHeaderName(name, headerName)) return remove(headerName); return m_uncommonHeaders.remove(name); }
static bool isForbiddenRequestHeader(const String& name) { HTTPHeaderName headerName; if (!findHTTPHeaderName(name, headerName)) return false; switch (headerName) { case HTTPHeaderName::AcceptCharset: case HTTPHeaderName::AcceptEncoding: case HTTPHeaderName::AccessControlRequestHeaders: case HTTPHeaderName::AccessControlRequestMethod: case HTTPHeaderName::Connection: case HTTPHeaderName::ContentLength: case HTTPHeaderName::ContentTransferEncoding: case HTTPHeaderName::Cookie: case HTTPHeaderName::Cookie2: case HTTPHeaderName::Date: case HTTPHeaderName::DNT: case HTTPHeaderName::Expect: case HTTPHeaderName::Host: case HTTPHeaderName::KeepAlive: case HTTPHeaderName::Origin: case HTTPHeaderName::Referer: case HTTPHeaderName::TE: case HTTPHeaderName::Trailer: case HTTPHeaderName::TransferEncoding: case HTTPHeaderName::Upgrade: case HTTPHeaderName::UserAgent: case HTTPHeaderName::Via: return true; default: return false; } }
String HTTPHeaderMap::get(const String& name) const { HTTPHeaderName headerName; if (!findHTTPHeaderName(name, headerName)) return m_uncommonHeaders.get(name); return m_commonHeaders.get(headerName); }
bool HTTPHeaderMap::contains(const String& name) const { HTTPHeaderName headerName; if (findHTTPHeaderName(name, headerName)) return contains(headerName); return m_uncommonHeaders.contains(name); }
// FIXME: Optimize these routines for HTTPHeaderMap keys and/or refactor them with XMLHttpRequest code. static bool isForbiddenHeaderName(const String& name) { HTTPHeaderName headerName; if (findHTTPHeaderName(name, headerName)) { switch (headerName) { case HTTPHeaderName::AcceptCharset: case HTTPHeaderName::AcceptEncoding: case HTTPHeaderName::AccessControlRequestHeaders: case HTTPHeaderName::AccessControlRequestMethod: case HTTPHeaderName::Connection: case HTTPHeaderName::ContentLength: case HTTPHeaderName::Cookie: case HTTPHeaderName::Cookie2: case HTTPHeaderName::Date: case HTTPHeaderName::DNT: case HTTPHeaderName::Expect: case HTTPHeaderName::Host: case HTTPHeaderName::KeepAlive: case HTTPHeaderName::Origin: case HTTPHeaderName::Referer: case HTTPHeaderName::TE: case HTTPHeaderName::Trailer: case HTTPHeaderName::TransferEncoding: case HTTPHeaderName::Upgrade: case HTTPHeaderName::Via: return true; default: break; } } return name.startsWithIgnoringASCIICase(ASCIILiteral("Sec-")) || name.startsWithIgnoringASCIICase(ASCIILiteral("Proxy-")); }
void HTTPHeaderMap::set(const String& name, const String& value) { HTTPHeaderName headerName; if (!findHTTPHeaderName(name, headerName)) { m_uncommonHeaders.set(name, value); return; } m_commonHeaders.set(headerName, value); }
void HTTPHeaderMap::add(const String& name, const String& value) { HTTPHeaderName headerName; if (!findHTTPHeaderName(name, headerName)) { auto result = m_uncommonHeaders.add(name, value); if (!result.isNewEntry) result.iterator->value = result.iterator->value + ", " + value; return; } add(headerName, value); }
void HTTPHeaderMap::set(CFStringRef name, const String& value) { // Fast path: avoid constructing a temporary String in the common header case. if (auto* nameCharacters = CFStringGetCStringPtr(name, kCFStringEncodingASCII)) { unsigned length = CFStringGetLength(name); HTTPHeaderName headerName; if (findHTTPHeaderName(StringView(reinterpret_cast<const LChar*>(nameCharacters), length), headerName)) m_commonHeaders.set(headerName, value); else m_uncommonHeaders.set(String(nameCharacters, length), value); return; } set(String(name), value); }
static bool isSimpleHeader(const String& name, const String& value) { HTTPHeaderName headerName; if (!findHTTPHeaderName(name, headerName)) return false; switch (headerName) { case HTTPHeaderName::Accept: case HTTPHeaderName::AcceptLanguage: case HTTPHeaderName::ContentLanguage: return true; case HTTPHeaderName::ContentType: { String mimeType = extractMIMETypeFromMediaType(value); return equalLettersIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded") || equalLettersIgnoringASCIICase(mimeType, "multipart/form-data") || equalLettersIgnoringASCIICase(mimeType, "text/plain"); } default: return false; } }
static bool shouldIgnoreHeaderForCacheReuse(const String& headerName) { HTTPHeaderName name; if (!findHTTPHeaderName(headerName, name)) return false; switch (name) { // FIXME: This list of headers that don't affect cache policy almost certainly isn't complete. case HTTPHeaderName::Accept: case HTTPHeaderName::CacheControl: case HTTPHeaderName::Pragma: case HTTPHeaderName::Purpose: case HTTPHeaderName::Referer: case HTTPHeaderName::UserAgent: return true; default: return false; } }
const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* end) { StringView name; String value; bool sawSecWebSocketExtensionsHeaderField = false; bool sawSecWebSocketAcceptHeaderField = false; bool sawSecWebSocketProtocolHeaderField = false; const char* p = start; for (; p < end; p++) { size_t consumedLength = parseHTTPHeader(p, end - p, m_failureReason, name, value); if (!consumedLength) return nullptr; p += consumedLength; // Stop once we consumed an empty line. if (name.isEmpty()) break; HTTPHeaderName headerName; if (!findHTTPHeaderName(name, headerName)) { // Evidence in the wild shows that services make use of custom headers in the handshake m_serverHandshakeResponse.addHTTPHeaderField(name.toString(), value); continue; } // https://tools.ietf.org/html/rfc7230#section-3.2.4 // "Newly defined header fields SHOULD limit their field values to US-ASCII octets." if ((headerName == HTTPHeaderName::SecWebSocketExtensions || headerName == HTTPHeaderName::SecWebSocketAccept || headerName == HTTPHeaderName::SecWebSocketProtocol) && !value.containsOnlyASCII()) { m_failureReason = makeString(name, " header value should only contain ASCII characters"); return nullptr; } if (headerName == HTTPHeaderName::SecWebSocketExtensions) { if (sawSecWebSocketExtensionsHeaderField) { m_failureReason = ASCIILiteral("The Sec-WebSocket-Extensions header must not appear more than once in an HTTP response"); return nullptr; } if (!m_extensionDispatcher.processHeaderValue(value)) { m_failureReason = m_extensionDispatcher.failureReason(); return nullptr; } sawSecWebSocketExtensionsHeaderField = true; } else { if (headerName == HTTPHeaderName::SecWebSocketAccept) { if (sawSecWebSocketAcceptHeaderField) { m_failureReason = ASCIILiteral("The Sec-WebSocket-Accept header must not appear more than once in an HTTP response"); return nullptr; } sawSecWebSocketAcceptHeaderField = true; } else if (headerName == HTTPHeaderName::SecWebSocketProtocol) { if (sawSecWebSocketProtocolHeaderField) { m_failureReason = ASCIILiteral("The Sec-WebSocket-Protocol header must not appear more than once in an HTTP response"); return nullptr; } sawSecWebSocketProtocolHeaderField = true; } m_serverHandshakeResponse.addHTTPHeaderField(headerName, value); } } return p; }