From 81ab22b6ffbdc7786558c0ca34f7348da3b2b349 Mon Sep 17 00:00:00 2001 From: Francesco Chemolli Date: Sat, 5 Sep 2015 20:52:17 +0200 Subject: [PATCH] Refactor HttpHeader into gperf-generated perfect hash --- src/HttpHeader.cc | 428 +++++++++------------------ src/HttpHeader.h | 11 +- src/HttpHeaderStat.h | 4 +- src/HttpHeaderTools.cc | 82 ++--- src/HttpHeaderTools.h | 2 +- src/HttpReply.cc | 21 +- src/ICP.h | 8 - src/Makefile.am | 33 ++- src/acl/HttpHeaderData.cc | 6 +- src/acl/HttpHeaderData.h | 5 +- src/adaptation/icap/ModXact.cc | 4 +- src/auth/UserRequest.cc | 4 +- src/base/LookupTable.h | 7 +- src/cache_cf.cc | 2 +- src/client_side_reply.cc | 10 +- src/external_acl.cc | 2 +- src/htcp.cc | 5 +- src/http.cc | 16 +- src/http/Makefile.am | 5 + src/http/RegisteredHeaders.cc | 156 ++++------ src/http/RegisteredHeaders.h | 74 +++-- src/http/RegisteredHeadersHash.cci | 381 ++++++++++++++++++++++++ src/http/RegisteredHeadersHash.gperf | 114 +++++++ 23 files changed, 860 insertions(+), 520 deletions(-) create mode 100644 src/http/RegisteredHeadersHash.cci create mode 100644 src/http/RegisteredHeadersHash.gperf diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc index 368253fe20..9db818baec 100644 --- a/src/HttpHeader.cc +++ b/src/HttpHeader.cc @@ -9,7 +9,7 @@ /* DEBUG: section 55 HTTP Header */ #include "squid.h" -//#include "base/LookupTable.h" // pulled by HttpHdrCc.h +#include "base/EnumIterator.h" #include "base64.h" #include "globals.h" #include "HttpHdrCc.h" @@ -61,160 +61,13 @@ */ // statistics counters for headers. clients must not allow Http::HdrType::BAD_HDR to be counted -std::vector headerStatsTable(Http::HdrType::ENUM_END); +std::vector headerStatsTable(Http::HdrType::enumEnd_); -/* - * headers with field values defined as #(values) in HTTP/1.1 - * Headers that are currently not recognized, are commented out. - */ -static HttpHeaderMask ListHeadersMask; /* set run-time using ListHeadersArr */ -static Http::HdrType ListHeadersArr[] = { - Http::HdrType::ACCEPT, - Http::HdrType::ACCEPT_CHARSET, - Http::HdrType::ACCEPT_ENCODING, - Http::HdrType::ACCEPT_LANGUAGE, - Http::HdrType::ACCEPT_RANGES, - Http::HdrType::ALLOW, - Http::HdrType::CACHE_CONTROL, - Http::HdrType::CONTENT_ENCODING, - Http::HdrType::CONTENT_LANGUAGE, - Http::HdrType::CONNECTION, - Http::HdrType::EXPECT, - Http::HdrType::IF_MATCH, - Http::HdrType::IF_NONE_MATCH, - Http::HdrType::KEY, - Http::HdrType::LINK, - Http::HdrType::PRAGMA, - Http::HdrType::PROXY_CONNECTION, - Http::HdrType::PROXY_SUPPORT, - Http::HdrType::TRANSFER_ENCODING, - Http::HdrType::UPGRADE, - Http::HdrType::VARY, - Http::HdrType::VIA, - Http::HdrType::WARNING, - Http::HdrType::WWW_AUTHENTICATE, - Http::HdrType::AUTHENTICATION_INFO, - Http::HdrType::PROXY_AUTHENTICATION_INFO, - /* Http::HdrType::TE, Http::HdrType::TRAILER */ -#if X_ACCELERATOR_VARY - Http::HdrType::HDR_X_ACCELERATOR_VARY, -#endif -#if USE_ADAPTATION - Http::HdrType::X_NEXT_SERVICES, -#endif - Http::HdrType::SURROGATE_CAPABILITY, - Http::HdrType::SURROGATE_CONTROL, - Http::HdrType::FORWARDED, - Http::HdrType::X_FORWARDED_FOR -}; - -/* general-headers */ -static Http::HdrType GeneralHeadersArr[] = { - Http::HdrType::CACHE_CONTROL, - Http::HdrType::CONNECTION, - Http::HdrType::DATE, - Http::HdrType::FORWARDED, - Http::HdrType::X_FORWARDED_FOR, - Http::HdrType::MIME_VERSION, - Http::HdrType::PRAGMA, - Http::HdrType::PROXY_CONNECTION, - Http::HdrType::TRANSFER_ENCODING, - Http::HdrType::UPGRADE, - /* Http::HdrType::TRAILER, */ - Http::HdrType::VIA, -}; - -/* entity-headers */ -static Http::HdrType EntityHeadersArr[] = { - Http::HdrType::ALLOW, - Http::HdrType::CONTENT_BASE, - Http::HdrType::CONTENT_ENCODING, - Http::HdrType::CONTENT_LANGUAGE, - Http::HdrType::CONTENT_LENGTH, - Http::HdrType::CONTENT_LOCATION, - Http::HdrType::CONTENT_MD5, - Http::HdrType::CONTENT_RANGE, - Http::HdrType::CONTENT_TYPE, - Http::HdrType::ETAG, - Http::HdrType::EXPIRES, - Http::HdrType::LAST_MODIFIED, - Http::HdrType::LINK, - Http::HdrType::OTHER -}; - -/* request-only headers */ +/* request-only headers. Used for cachemgr */ static HttpHeaderMask RequestHeadersMask; /* set run-time using RequestHeaders */ -static Http::HdrType RequestHeadersArr[] = { - Http::HdrType::ACCEPT, - Http::HdrType::ACCEPT_CHARSET, - Http::HdrType::ACCEPT_ENCODING, - Http::HdrType::ACCEPT_LANGUAGE, - Http::HdrType::AUTHORIZATION, - Http::HdrType::EXPECT, - Http::HdrType::FROM, - Http::HdrType::HOST, - Http::HdrType::HTTP2_SETTINGS, - Http::HdrType::IF_MATCH, - Http::HdrType::IF_MODIFIED_SINCE, - Http::HdrType::IF_NONE_MATCH, - Http::HdrType::IF_RANGE, - Http::HdrType::IF_UNMODIFIED_SINCE, - Http::HdrType::MAX_FORWARDS, - Http::HdrType::ORIGIN, - Http::HdrType::PROXY_AUTHORIZATION, - Http::HdrType::RANGE, - Http::HdrType::REFERER, - Http::HdrType::REQUEST_RANGE, - Http::HdrType::TE, - Http::HdrType::USER_AGENT, - Http::HdrType::SURROGATE_CAPABILITY -}; -/* reply-only headers */ +/* reply-only headers. Used for cachemgr */ static HttpHeaderMask ReplyHeadersMask; /* set run-time using ReplyHeaders */ -static Http::HdrType ReplyHeadersArr[] = { - Http::HdrType::ACCEPT_ENCODING, - Http::HdrType::ACCEPT_RANGES, - Http::HdrType::AGE, - Http::HdrType::KEY, - Http::HdrType::LOCATION, - Http::HdrType::PROXY_AUTHENTICATE, - Http::HdrType::PUBLIC, - Http::HdrType::RETRY_AFTER, - Http::HdrType::SERVER, - Http::HdrType::SET_COOKIE, - Http::HdrType::SET_COOKIE2, - Http::HdrType::VARY, - Http::HdrType::WARNING, - Http::HdrType::WWW_AUTHENTICATE, - Http::HdrType::X_CACHE, - Http::HdrType::X_CACHE_LOOKUP, - Http::HdrType::X_REQUEST_URI, -#if X_ACCELERATOR_VARY - Http::HdrType::HDR_X_ACCELERATOR_VARY, -#endif -#if USE_ADAPTATION - Http::HdrType::X_NEXT_SERVICES, -#endif - Http::HdrType::X_SQUID_ERROR, - Http::HdrType::SURROGATE_CONTROL -}; - -/* hop-by-hop headers */ -static HttpHeaderMask HopByHopHeadersMask; -static Http::HdrType HopByHopHeadersArr[] = { - Http::HdrType::ALTERNATE_PROTOCOL, - Http::HdrType::CONNECTION, - Http::HdrType::HTTP2_SETTINGS, - Http::HdrType::KEEP_ALIVE, - /*Http::HdrType::PROXY_AUTHENTICATE, // removal handled specially for peer login */ - Http::HdrType::PROXY_AUTHORIZATION, - Http::HdrType::TE, - Http::HdrType::TRAILER, - Http::HdrType::TRANSFER_ENCODING, - Http::HdrType::UPGRADE, - Http::HdrType::PROXY_CONNECTION -}; /* header accounting */ // NP: keep in sync with enum http_hdr_owner_type @@ -240,7 +93,9 @@ static int HeaderEntryParsedCount = 0; class StoreEntry; -static void httpHeaderNoteParsedEntry(Http::HdrType id, String const &value, int error); +// update parse statistics for header id; if error is true also account +// for errors and write to debug log what happened +static void httpHeaderNoteParsedEntry(Http::HdrType id, String const &value, bool error); static void httpHeaderStatDump(const HttpHeaderStat * hs, StoreEntry * e); /** store report about current header usage and other stats */ static void httpHeaderStoreReport(StoreEntry * e); @@ -261,28 +116,15 @@ void httpHeaderInitModule(void) { /* check that we have enough space for masks */ - assert(8 * sizeof(HttpHeaderMask) >= Http::HdrType::ENUM_END); - - // check invariant: for each index in headerTable, (int)headerTable[index] = index - for (int i = 0; Http::HeaderTable[i].name; ++i) - assert(Http::HeaderTable[i].id == i); - - /* create masks. XXX: migrate to std::vector? */ - httpHeaderMaskInit(&ListHeadersMask, 0); - httpHeaderCalcMask(&ListHeadersMask, ListHeadersArr, countof(ListHeadersArr)); - - httpHeaderMaskInit(&ReplyHeadersMask, 0); - httpHeaderCalcMask(&ReplyHeadersMask, ReplyHeadersArr, countof(ReplyHeadersArr)); - httpHeaderCalcMask(&ReplyHeadersMask, GeneralHeadersArr, countof(GeneralHeadersArr)); - httpHeaderCalcMask(&ReplyHeadersMask, EntityHeadersArr, countof(EntityHeadersArr)); - - httpHeaderMaskInit(&RequestHeadersMask, 0); - httpHeaderCalcMask(&RequestHeadersMask, RequestHeadersArr, countof(RequestHeadersArr)); - httpHeaderCalcMask(&RequestHeadersMask, GeneralHeadersArr, countof(GeneralHeadersArr)); - httpHeaderCalcMask(&RequestHeadersMask, EntityHeadersArr, countof(EntityHeadersArr)); - - httpHeaderMaskInit(&HopByHopHeadersMask, 0); - httpHeaderCalcMask(&HopByHopHeadersMask, HopByHopHeadersArr, countof(HopByHopHeadersArr)); + assert(8 * sizeof(HttpHeaderMask) >= Http::HdrType::enumEnd_); + + // masks are needed for stats page still + for (auto h : WholeEnum()) { + if (Http::HeaderLookupTable.lookup(h).request) + CBIT_SET(RequestHeadersMask,h); + if (Http::HeaderLookupTable.lookup(h).reply) + CBIT_SET(ReplyHeadersMask,h); + } /* header stats initialized by class constructor */ assert(HttpHeaderStatCount == hoReply + 1); @@ -363,7 +205,7 @@ HttpHeader::clean() HttpHeaderStats[owner].busyDestroyedCount += entries.size() > 0; } // if (owner <= hoReply) - for(HttpHeaderEntry *e : entries) { + for (HttpHeaderEntry *e : entries) { if (e == nullptr) continue; if (!Http::any_valid_header(e->id)) { @@ -386,25 +228,16 @@ HttpHeader::clean() void HttpHeader::append(const HttpHeader * src) { - const HttpHeaderEntry *e; - HttpHeaderPos pos = HttpHeaderInitPos; assert(src); assert(src != this); debugs(55, 7, "appending hdr: " << this << " += " << src); - while ((e = src->getEntry(&pos))) { - addEntry(e->clone()); + for (auto e : src->entries) { + if (e) + addEntry(e->clone()); } } -/* use fresh entries to replace old ones */ -void -httpHeaderUpdate(HttpHeader * old, const HttpHeader * fresh, const HttpHeaderMask * denied_mask) -{ - assert (old); - old->update (fresh, denied_mask); -} - void HttpHeader::update (HttpHeader const *fresh, HttpHeaderMask const *denied_mask) { @@ -432,20 +265,12 @@ HttpHeader::update (HttpHeader const *fresh, HttpHeaderMask const *denied_mask) if (denied_mask && CBIT_TEST(*denied_mask, e->id)) continue; - debugs(55, 7, "Updating header '" << Http::HeaderTable[e->id].name << "' in cached entry"); + debugs(55, 7, "Updating header '" << Http::HeaderLookupTable.lookup(e->id).name << "' in cached entry"); addEntry(e->clone()); } } -/* just handy in parsing: resets and returns false */ -int -HttpHeader::reset() -{ - clean(); - return 0; -} - int HttpHeader::parse(const char *header_start, size_t hdrLen) { @@ -465,7 +290,8 @@ HttpHeader::parse(const char *header_start, size_t hdrLen) debugs(55, DBG_IMPORTANT, "WARNING: HTTP header contains NULL characters {" << getStringPrefix(header_start, nulpos-header_start) << "}\nNULL\n{" << getStringPrefix(nulpos+1, hdrLen-(nulpos-header_start)-1)); PROF_stop(HttpHeaderParse); - return reset(); + clean(); + return 0; } /* common format headers are ":[ws]" lines delimited by . @@ -481,7 +307,8 @@ HttpHeader::parse(const char *header_start, size_t hdrLen) if (!field_ptr) { // missing PROF_stop(HttpHeaderParse); - return reset(); + clean(); + return 0; } field_end = field_ptr; @@ -502,7 +329,8 @@ HttpHeader::parse(const char *header_start, size_t hdrLen) "header field to prevent request smuggling attacks: {" << getStringPrefix(header_start, hdrLen) << "}"); PROF_stop(HttpHeaderParse); - return reset(); + clean(); + return 0; } } } @@ -521,7 +349,8 @@ HttpHeader::parse(const char *header_start, size_t hdrLen) } } else { PROF_stop(HttpHeaderParse); - return reset(); + clean(); + return 0; } } @@ -529,7 +358,8 @@ HttpHeader::parse(const char *header_start, size_t hdrLen) debugs(55, warnOnError, "WARNING: Blank continuation line in HTTP header {" << getStringPrefix(header_start, hdrLen) << "}"); PROF_stop(HttpHeaderParse); - return reset(); + clean(); + return 0; } } while (field_ptr < header_end && (*field_ptr == ' ' || *field_ptr == '\t')); @@ -538,7 +368,8 @@ HttpHeader::parse(const char *header_start, size_t hdrLen) debugs(55, warnOnError, "WARNING: unparseable HTTP header field near {" << getStringPrefix(field_start, hdrLen-(field_start-header_start)) << "}"); PROF_stop(HttpHeaderParse); - return reset(); + clean(); + return 0; } break; /* terminating blank line */ @@ -553,7 +384,8 @@ HttpHeader::parse(const char *header_start, size_t hdrLen) continue; PROF_stop(HttpHeaderParse); - return reset(); + clean(); + return 0; } // XXX: RFC 7230 Section 3.3.3 item #4 requires sending a 502 error in @@ -567,7 +399,8 @@ HttpHeader::parse(const char *header_start, size_t hdrLen) if (!Config.onoff.relaxed_header_parser) { delete e; PROF_stop(HttpHeaderParse); - return reset(); + clean(); + return 0; } if (!httpHeaderParseOffset(e->value.termedBuf(), &l1)) { @@ -591,7 +424,8 @@ HttpHeader::parse(const char *header_start, size_t hdrLen) continue; PROF_stop(HttpHeaderParse); - return reset(); + clean(); + return 0; } } @@ -602,7 +436,8 @@ HttpHeader::parse(const char *header_start, size_t hdrLen) if (!Config.onoff.relaxed_header_parser) { delete e; PROF_stop(HttpHeaderParse); - return reset(); + clean(); + return 0; } } @@ -690,10 +525,8 @@ HttpHeader::getEntry(HttpHeaderPos * pos) const HttpHeaderEntry * HttpHeader::findEntry(Http::HdrType id) const { - HttpHeaderPos pos = HttpHeaderInitPos; - HttpHeaderEntry *e; assert(any_registered_header(id)); - assert(!CBIT_TEST(ListHeadersMask, id)); + assert(!Http::HeaderLookupTable.lookup(id).list); /* check mask first */ @@ -701,15 +534,14 @@ HttpHeader::findEntry(Http::HdrType id) const return NULL; /* looks like we must have it, do linear search */ - while ((e = getEntry(&pos))) { - if (e->id == id) + for (auto e : entries) { + if (e && e->id == id) return e; } /* hm.. we thought it was there, but it was not found */ - assert(0); - - return NULL; /* not reached */ + assert(false); + return nullptr; /* not reached */ } /* @@ -718,25 +550,21 @@ HttpHeader::findEntry(Http::HdrType id) const HttpHeaderEntry * HttpHeader::findLastEntry(Http::HdrType id) const { - HttpHeaderPos pos = HttpHeaderInitPos; - HttpHeaderEntry *e; - HttpHeaderEntry *result = NULL; assert(any_registered_header(id)); - assert(!CBIT_TEST(ListHeadersMask, id)); + assert(!Http::HeaderLookupTable.lookup(id).list); /* check mask first */ - if (!CBIT_TEST(mask, id)) return NULL; - /* looks like we must have it, do linear search */ - while ((e = getEntry(&pos))) { - if (e->id == id) - result = e; + for (auto e = entries.rbegin(); e != entries.rend(); ++e) { + if (*e && (*e)->id == id) + return *e; } - assert(result); /* must be there! */ - return result; + /* hm.. we thought it was there, but it was not found */ + assert(false); + return nullptr; /* not reached */ } /* @@ -765,19 +593,23 @@ HttpHeader::delByName(const char *name) int HttpHeader::delById(Http::HdrType id) { - int count = 0; - HttpHeaderPos pos = HttpHeaderInitPos; - HttpHeaderEntry *e; debugs(55, 8, this << " del-by-id " << id); assert(any_registered_header(id)); + int count=0; if (!CBIT_TEST(mask, id)) return 0; - while ((e = getEntry(&pos))) { - if (e->id == id) - delAt(pos, count); - } + //replace matching items with nil and count them + std::replace_if(entries.begin(), entries.end(), + [&](const HttpHeaderEntry *e) { + if (e && e->id == id) { + ++count; + return true; + } + return false; + }, + nullptr); CBIT_CLR(mask, id); assert(count); @@ -811,9 +643,8 @@ void HttpHeader::compact() { // TODO: optimize removal, or possibly make it so that's not needed. - std::vector::iterator newend; - newend = std::remove(entries.begin(), entries.end(), static_cast(NULL)); - entries.resize(newend-entries.begin()); + entries.erase( std::remove(entries.begin(), entries.end(), nullptr), + entries.end()); } /* @@ -824,9 +655,9 @@ HttpHeader::refreshMask() { httpHeaderMaskInit(&mask, 0); debugs(55, 7, "refreshing the mask in hdr " << this); - HttpHeaderPos pos = HttpHeaderInitPos; - while (HttpHeaderEntry *e = getEntry(&pos)) { - CBIT_SET(mask, e->id); + for (auto e : entries) { + if (e) + CBIT_SET(mask, e->id); } } @@ -883,17 +714,15 @@ HttpHeader::insertEntry(HttpHeaderEntry * e) bool HttpHeader::getList(Http::HdrType id, String *s) const { - HttpHeaderEntry *e; - HttpHeaderPos pos = HttpHeaderInitPos; debugs(55, 9, this << " joining for id " << id); /* only fields from ListHeaders array can be "listed" */ - assert(CBIT_TEST(ListHeadersMask, id)); + assert(Http::HeaderLookupTable.lookup(id).list); if (!CBIT_TEST(mask, id)) return false; - while ((e = getEntry(&pos))) { - if (e->id == id) + for (auto e: entries) { + if (e && e->id == id) strListAdd(s, e->value.termedBuf(), ','); } @@ -904,7 +733,7 @@ HttpHeader::getList(Http::HdrType id, String *s) const */ /* temporary warning: remove it? (Is it useful for diagnostics ?) */ if (!s->size()) - debugs(55, 3, "empty list header: " << Http::HeaderTable[id].name << "(" << id << ")"); + debugs(55, 3, "empty list header: " << Http::HeaderLookupTable.lookup(id).name << "(" << id << ")"); else debugs(55, 6, this << ": joined for id " << id << ": " << s); @@ -919,7 +748,7 @@ HttpHeader::getList(Http::HdrType id) const HttpHeaderPos pos = HttpHeaderInitPos; debugs(55, 9, this << "joining for id " << id); /* only fields from ListHeaders array can be "listed" */ - assert(CBIT_TEST(ListHeadersMask, id)); + assert(Http::HeaderLookupTable.lookup(id).list); if (!CBIT_TEST(mask, id)) return String(); @@ -938,7 +767,7 @@ HttpHeader::getList(Http::HdrType id) const */ /* temporary warning: remove it? (Is it useful for diagnostics ?) */ if (!s.size()) - debugs(55, 3, "empty list header: " << Http::HeaderTable[id].name << "(" << id << ")"); + debugs(55, 3, "empty list header: " << Http::HeaderLookupTable.lookup(id).name << "(" << id << ")"); else debugs(55, 6, this << ": joined for id " << id << ": " << s); @@ -951,7 +780,7 @@ HttpHeader::getStrOrList(Http::HdrType id) const { HttpHeaderEntry *e; - if (CBIT_TEST(ListHeadersMask, id)) + if (Http::HeaderLookupTable.lookup(id).list) return getList(id); if ((e = findEntry(id))) @@ -965,6 +794,15 @@ HttpHeader::getStrOrList(Http::HdrType id) const */ String HttpHeader::getByName(const char *name) const +{ + String result; + // ignore presence: return undefined string if an empty header is present + (void)getByNameIfPresent(name, strlen(name), result); + return result; +} + +String +HttpHeader::getByName(const SBuf &name) const { String result; // ignore presence: return undefined string if an empty header is present @@ -972,8 +810,33 @@ HttpHeader::getByName(const char *name) const return result; } +String +HttpHeader::getById(Http::HdrType id) const +{ + String result; + (void)getByIdIfPresent(id,result); + return result; +} + +bool +HttpHeader::getByNameIfPresent(const SBuf &s, String &result) const +{ + return getByNameIfPresent(s.rawContent(), s.length(), result); +} + +bool +HttpHeader::getByIdIfPresent(Http::HdrType id, String &result) const +{ + if (id == Http::HdrType::BAD_HDR) + return false; + if (!has(id)) + return false; + result = getStrOrList(id); + return true; +} + bool -HttpHeader::getByNameIfPresent(const char *name, String &result) const +HttpHeader::getByNameIfPresent(const char *name, int namelen, String &result) const { Http::HdrType id; HttpHeaderPos pos = HttpHeaderInitPos; @@ -982,13 +845,11 @@ HttpHeader::getByNameIfPresent(const char *name, String &result) const assert(name); /* First try the quick path */ - id = Http::HeaderLookupTable.lookup(SBuf(name)); + id = Http::HeaderLookupTable.lookup(name,namelen).id; if (id != Http::HdrType::BAD_HDR) { - if (!has(id)) - return false; - result = getStrOrList(id); - return true; + if (getByIdIfPresent(id, result)) + return true; } /* Sorry, an unknown header name. Do linear search */ @@ -1072,7 +933,7 @@ void HttpHeader::putInt(Http::HdrType id, int number) { assert(any_registered_header(id)); - assert(Http::HeaderTable[id].type == Http::HdrFieldType::ftInt); /* must be of an appropriate type */ + assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftInt); /* must be of an appropriate type */ assert(number >= 0); addEntry(new HttpHeaderEntry(id, NULL, xitoa(number))); } @@ -1081,7 +942,7 @@ void HttpHeader::putInt64(Http::HdrType id, int64_t number) { assert(any_registered_header(id)); - assert(Http::HeaderTable[id].type == Http::HdrFieldType::ftInt64); /* must be of an appropriate type */ + assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftInt64); /* must be of an appropriate type */ assert(number >= 0); addEntry(new HttpHeaderEntry(id, NULL, xint64toa(number))); } @@ -1090,25 +951,16 @@ void HttpHeader::putTime(Http::HdrType id, time_t htime) { assert(any_registered_header(id)); - assert(Http::HeaderTable[id].type == Http::HdrFieldType::ftDate_1123); /* must be of an appropriate type */ + assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftDate_1123); /* must be of an appropriate type */ assert(htime >= 0); addEntry(new HttpHeaderEntry(id, NULL, mkrfc1123(htime))); } -void -HttpHeader::insertTime(Http::HdrType id, time_t htime) -{ - assert(any_registered_header(id)); - assert(Http::HeaderTable[id].type == Http::HdrFieldType::ftDate_1123); /* must be of an appropriate type */ - assert(htime >= 0); - insertEntry(new HttpHeaderEntry(id, NULL, mkrfc1123(htime))); -} - void HttpHeader::putStr(Http::HdrType id, const char *str) { assert(any_registered_header(id)); - assert(Http::HeaderTable[id].type == Http::HdrFieldType::ftStr); /* must be of an appropriate type */ + assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftStr); /* must be of an appropriate type */ assert(str); addEntry(new HttpHeaderEntry(id, NULL, str)); } @@ -1205,7 +1057,7 @@ int HttpHeader::getInt(Http::HdrType id) const { assert(any_registered_header(id)); - assert(Http::HeaderTable[id].type == Http::HdrFieldType::ftInt); /* must be of an appropriate type */ + assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftInt); /* must be of an appropriate type */ HttpHeaderEntry *e; if ((e = findEntry(id))) @@ -1218,7 +1070,7 @@ int64_t HttpHeader::getInt64(Http::HdrType id) const { assert(any_registered_header(id)); - assert(Http::HeaderTable[id].type == Http::HdrFieldType::ftInt64); /* must be of an appropriate type */ + assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftInt64); /* must be of an appropriate type */ HttpHeaderEntry *e; if ((e = findEntry(id))) @@ -1233,7 +1085,7 @@ HttpHeader::getTime(Http::HdrType id) const HttpHeaderEntry *e; time_t value = -1; assert(any_registered_header(id)); - assert(Http::HeaderTable[id].type == Http::HdrFieldType::ftDate_1123); /* must be of an appropriate type */ + assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftDate_1123); /* must be of an appropriate type */ if ((e = findEntry(id))) { value = parse_rfc1123(e->value.termedBuf()); @@ -1249,10 +1101,10 @@ HttpHeader::getStr(Http::HdrType id) const { HttpHeaderEntry *e; assert(any_registered_header(id)); - assert(Http::HeaderTable[id].type == Http::HdrFieldType::ftStr); /* must be of an appropriate type */ + assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftStr); /* must be of an appropriate type */ if ((e = findEntry(id))) { - httpHeaderNoteParsedEntry(e->id, e->value, 0); /* no errors are possible */ + httpHeaderNoteParsedEntry(e->id, e->value, false); /* no errors are possible */ return e->value.termedBuf(); } @@ -1265,10 +1117,10 @@ HttpHeader::getLastStr(Http::HdrType id) const { HttpHeaderEntry *e; assert(any_registered_header(id)); - assert(Http::HeaderTable[id].type == Http::HdrFieldType::ftStr); /* must be of an appropriate type */ + assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftStr); /* must be of an appropriate type */ if ((e = findLastEntry(id))) { - httpHeaderNoteParsedEntry(e->id, e->value, 0); /* no errors are possible */ + httpHeaderNoteParsedEntry(e->id, e->value, false); /* no errors are possible */ return e->value.termedBuf(); } @@ -1403,7 +1255,7 @@ HttpHeader::getETag(Http::HdrType id) const { ETag etag = {NULL, -1}; HttpHeaderEntry *e; - assert(Http::HeaderTable[id].type == Http::HdrFieldType::ftETag); /* must be of an appropriate type */ + assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftETag); /* must be of an appropriate type */ if ((e = findEntry(id))) etagParseInit(&etag, e->value.termedBuf()); @@ -1416,7 +1268,7 @@ HttpHeader::getTimeOrTag(Http::HdrType id) const { TimeOrTag tot; HttpHeaderEntry *e; - assert(Http::HeaderTable[id].type == Http::HdrFieldType::ftDate_1123_or_ETag); /* must be of an appropriate type */ + assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftDate_1123_or_ETag); /* must be of an appropriate type */ memset(&tot, 0, sizeof(tot)); if ((e = findEntry(id))) { @@ -1448,7 +1300,7 @@ HttpHeaderEntry::HttpHeaderEntry(Http::HdrType anId, const char *aName, const ch id = anId; if (id != Http::HdrType::OTHER) - name = Http::HeaderTable[id].name; + name = Http::HeaderLookupTable.lookup(id).name; else name = aName; @@ -1511,7 +1363,7 @@ HttpHeaderEntry::parse(const char *field_start, const char *field_end) debugs(55, 9, "parsing HttpHeaderEntry: near '" << getStringPrefix(field_start, field_end-field_start) << "'"); /* is it a "known" field? */ - Http::HdrType id = Http::HeaderLookupTable.lookup(SBuf(field_start,name_len)); + Http::HdrType id = Http::HeaderLookupTable.lookup(field_start,name_len).id; debugs(55, 9, "got hdr-id=" << id); String name; @@ -1525,7 +1377,7 @@ HttpHeaderEntry::parse(const char *field_start, const char *field_end) if (id == Http::HdrType::OTHER) name.limitInit(field_start, name_len); else - name = Http::HeaderTable[id].name; + name = Http::HeaderLookupTable.lookup(id).name; /* trim field value */ while (value_start < field_end && xisspace(*value_start)) @@ -1576,7 +1428,7 @@ HttpHeaderEntry::getInt() const { int val = -1; int ok = httpHeaderParseInt(value.termedBuf(), &val); - httpHeaderNoteParsedEntry(id, value, !ok); + httpHeaderNoteParsedEntry(id, value, ok == 0); /* XXX: Should we check ok - ie * return ok ? -1 : value; */ @@ -1588,7 +1440,7 @@ HttpHeaderEntry::getInt64() const { int64_t val = -1; int ok = httpHeaderParseOffset(value.termedBuf(), &val); - httpHeaderNoteParsedEntry(id, value, !ok); + httpHeaderNoteParsedEntry(id, value, ok == 0); /* XXX: Should we check ok - ie * return ok ? -1 : value; */ @@ -1596,7 +1448,7 @@ HttpHeaderEntry::getInt64() const } static void -httpHeaderNoteParsedEntry(Http::HdrType id, String const &context, int error) +httpHeaderNoteParsedEntry(Http::HdrType id, String const &context, bool error) { if (id != Http::HdrType::BAD_HDR) ++ headerStatsTable[id].parsCount; @@ -1604,7 +1456,7 @@ httpHeaderNoteParsedEntry(Http::HdrType id, String const &context, int error) if (error) { if (id != Http::HdrType::BAD_HDR) ++ headerStatsTable[id].errCount; - debugs(55, 2, "cannot parse hdr field: '" << Http::HeaderTable[id].name << ": " << context << "'"); + debugs(55, 2, "cannot parse hdr field: '" << Http::HeaderLookupTable.lookup(id).name << ": " << context << "'"); } } @@ -1621,7 +1473,7 @@ httpHeaderFieldStatDumper(StoreEntry * sentry, int, double val, double, int coun { const int id = static_cast(val); const bool valid_id = Http::any_valid_header(static_cast(id)); - const char *name = valid_id ? Http::HeaderTable[id].name : "INVALID"; + const char *name = valid_id ? Http::HeaderLookupTable.lookup(static_cast(id)).name : "INVALID"; int visible = count > 0; /* for entries with zero count, list only those that belong to current type of message */ @@ -1696,11 +1548,11 @@ httpHeaderStoreReport(StoreEntry * e) "id", "name", "#alive", "%err", "%repeat"); // scan heaaderTable and output - for (int j = 0; Http::HeaderTable[j].name != nullptr; ++j) { - auto stats = headerStatsTable[j]; + for (auto h : WholeEnum()) { + auto stats = headerStatsTable[h]; storeAppendPrintf(e, "%2d\t %-25s\t %5d\t %6.3f\t %6.3f\n", - Http::HeaderTable[j].id, - Http::HeaderTable[j].name, + Http::HeaderLookupTable.lookup(h).id, + Http::HeaderLookupTable.lookup(h).name, stats.aliveCount, xpercent(stats.errCount, stats.parsCount), xpercent(stats.repCount, stats.seenCount)); @@ -1771,7 +1623,7 @@ HttpHeader::removeHopByHopEntries() int headers_deleted = 0; while ((e = getEntry(&pos))) { Http::HdrType id = e->id; - if (CBIT_TEST(HopByHopHeadersMask, id)) { + if (Http::HeaderLookupTable.lookup(id).hopbyhop) { delAt(pos, headers_deleted); CBIT_CLR(mask, id); } diff --git a/src/HttpHeader.h b/src/HttpHeader.h index c7a6eb6912..e65fcaebbf 100644 --- a/src/HttpHeader.h +++ b/src/HttpHeader.h @@ -83,7 +83,6 @@ public: void append(const HttpHeader * src); void update (HttpHeader const *fresh, HttpHeaderMask const *denied_mask); void compact(); - int reset(); int parse(const char *header_start, size_t len); void packInto(Packable * p, bool mask_sensitive_info=false) const; HttpHeaderEntry *getEntry(HttpHeaderPos * pos) const; @@ -98,16 +97,20 @@ public: bool getList(Http::HdrType id, String *s) const; bool conflictingContentLength() const { return conflictingContentLength_; } String getStrOrList(Http::HdrType id) const; + String getByName(const SBuf &name) const; String getByName(const char *name) const; + String getById(Http::HdrType id) const; + /// sets value and returns true iff a [possibly empty] field identified by id is there + bool getByIdIfPresent(Http::HdrType id, String &result) const; /// sets value and returns true iff a [possibly empty] named field is there - bool getByNameIfPresent(const char *name, String &value) const; + bool getByNameIfPresent(const SBuf &s, String &value) const; + bool getByNameIfPresent(const char *name, int namelen, String &value) const; String getByNameListMember(const char *name, const char *member, const char separator) const; String getListMember(Http::HdrType id, const char *member, const char separator) const; int has(Http::HdrType id) const; void putInt(Http::HdrType id, int number); void putInt64(Http::HdrType id, int64_t number); void putTime(Http::HdrType id, time_t htime); - void insertTime(Http::HdrType id, time_t htime); void putStr(Http::HdrType id, const char *str); void putAuth(const char *auth_scheme, const char *realm); void putCc(const HttpHdrCc * cc); @@ -153,8 +156,6 @@ int httpHeaderParseQuotedString(const char *start, const int len, String *val); /// quotes string using RFC 7230 quoted-string rules SBuf httpHeaderQuoteString(const char *raw); -int httpHeaderHasByNameListMember(const HttpHeader * hdr, const char *name, const char *member, const char separator); -void httpHeaderUpdate(HttpHeader * old, const HttpHeader * fresh, const HttpHeaderMask * denied_mask); void httpHeaderCalcMask(HttpHeaderMask * mask, Http::HdrType http_hdr_type_enums[], size_t count); inline bool diff --git a/src/HttpHeaderStat.h b/src/HttpHeaderStat.h index 6610c7c9a4..eaad3c8880 100644 --- a/src/HttpHeaderStat.h +++ b/src/HttpHeaderStat.h @@ -27,7 +27,7 @@ public: busyDestroyedCount(0) { hdrUCountDistr.enumInit(32); /* not a real enum */ - fieldTypeDistr.enumInit(Http::HdrType::ENUM_END); + fieldTypeDistr.enumInit(Http::HdrType::enumEnd_); ccTypeDistr.enumInit(HttpHdrCcType::CC_ENUM_END); scTypeDistr.enumInit(SC_ENUM_END); } @@ -43,7 +43,7 @@ public: { assert(label); hdrUCountDistr.enumInit(32); /* not a real enum */ - fieldTypeDistr.enumInit(Http::HdrType::ENUM_END); + fieldTypeDistr.enumInit(Http::HdrType::enumEnd_); ccTypeDistr.enumInit(HttpHdrCcType::CC_ENUM_END); scTypeDistr.enumInit(SC_ENUM_END); } diff --git a/src/HttpHeaderTools.cc b/src/HttpHeaderTools.cc index a8d6ac7dfa..6a352a0062 100644 --- a/src/HttpHeaderTools.cc +++ b/src/HttpHeaderTools.cc @@ -11,6 +11,7 @@ #include "squid.h" #include "acl/FilledChecklist.h" #include "acl/Gadgets.h" +#include "base/EnumIterator.h" #include "client_side.h" #include "client_side_request.h" #include "comm/Connection.h" @@ -45,21 +46,6 @@ httpHeaderMaskInit(HttpHeaderMask * mask, int value) memset(mask, value, sizeof(*mask)); } -/** calculates a bit mask of a given array; does not reset mask! */ -void -httpHeaderCalcMask(HttpHeaderMask * mask, Http::HdrType http_hdr_type_enums[], size_t count) -{ - size_t i; - const int * enums = (const int *) http_hdr_type_enums; - assert(mask && enums); - assert(count < sizeof(*mask) * 8); /* check for overflow */ - - for (i = 0; i < count; ++i) { - assert(!CBIT_TEST(*mask, enums[i])); /* check for duplicates */ - CBIT_SET(*mask, enums[i]); - } -} - /* same as httpHeaderPutStr, but formats the string using snprintf first */ void httpHeaderPutStrf(HttpHeader * hdr, Http::HdrType id, const char *fmt,...) @@ -155,9 +141,12 @@ httpHeaderParseOffset(const char *start, int64_t * value) { errno = 0; int64_t res = strtoll(start, NULL, 10); - if (!res && EINVAL == errno) /* maybe not portable? */ + if (!res && EINVAL == errno) { /* maybe not portable? */ + debugs(66, 7, "failed to parse offset in " << start); return 0; + } *value = res; + debugs(66, 7, "offset " << start << " parsed as " << res); return 1; } @@ -295,13 +284,16 @@ httpHdrMangle(HttpHeaderEntry * e, HttpRequest * request, int req_or_rep) } /* manglers are not configured for this message kind */ - if (!hms) + if (!hms) { + debugs(66, 7, "no manglers configured for message kind " << req_or_rep); return 1; + } const headerMangler *hm = hms->find(*e); /* mangler or checklist went away. default allow */ if (!hm || !hm->access_list) { + debugs(66, 7, "couldn't find mangler or access list. Allowing"); return 1; } @@ -309,15 +301,18 @@ httpHdrMangle(HttpHeaderEntry * e, HttpRequest * request, int req_or_rep) if (checklist.fastCheck() == ACCESS_ALLOWED) { /* aclCheckFast returns true for allow. */ + debugs(66, 7, "checklist for mangler is positive. Mangle"); retval = 1; } else if (NULL == hm->replacement) { /* It was denied, and we don't have any replacement */ + debugs(66, 7, "checklist denied, we have no replacement. Pass"); retval = 0; } else { /* It was denied, but we have a replacement. Replace the * header on the fly, and return that the new header * is allowed. */ + debugs(66, 7, "checklist denied but we have replacement. Replace"); e->value = hm->replacement; retval = 1; } @@ -374,12 +369,11 @@ HeaderManglers::HeaderManglers() HeaderManglers::~HeaderManglers() { - for (int i = 0; i < Http::HdrType::ENUM_END; ++i) + for (auto i : WholeEnum()) header_mangler_clean(known[i]); - typedef ManglersByName::iterator MBNI; - for (MBNI i = custom.begin(); i != custom.end(); ++i) - header_mangler_clean(i->second); + for (auto i : custom) + header_mangler_clean(i.second); header_mangler_clean(all); } @@ -387,13 +381,11 @@ HeaderManglers::~HeaderManglers() void HeaderManglers::dumpAccess(StoreEntry * entry, const char *name) const { - for (int i = 0; Http::HeaderTable[i].name != nullptr; ++i) { - header_mangler_dump_access(entry, name, known[i], Http::HeaderTable[i].name); - } + for (auto id : WholeEnum()) + header_mangler_dump_access(entry, name, known[id], Http::HeaderLookupTable.lookup(id).name); - typedef ManglersByName::const_iterator MBNCI; - for (MBNCI i = custom.begin(); i != custom.end(); ++i) - header_mangler_dump_access(entry, name, i->second, i->first.c_str()); + for (auto i : custom) + header_mangler_dump_access(entry, name, i.second, i.first.c_str()); header_mangler_dump_access(entry, name, all, "All"); } @@ -401,14 +393,12 @@ HeaderManglers::dumpAccess(StoreEntry * entry, const char *name) const void HeaderManglers::dumpReplacement(StoreEntry * entry, const char *name) const { - for (int i = 0; Http::HeaderTable[i].name != nullptr; ++i) { - header_mangler_dump_replacement(entry, name, known[i],Http::HeaderTable[i].name); + for (auto id : WholeEnum()) { + header_mangler_dump_replacement(entry, name, known[id], Http::HeaderLookupTable.lookup(id).name); } - typedef ManglersByName::const_iterator MBNCI; - for (MBNCI i = custom.begin(); i != custom.end(); ++i) { - header_mangler_dump_replacement(entry, name, i->second, - i->first.c_str()); + for (auto i: custom) { + header_mangler_dump_replacement(entry, name, i.second, i.first.c_str()); } header_mangler_dump_replacement(entry, name, all, "All"); @@ -417,26 +407,18 @@ HeaderManglers::dumpReplacement(StoreEntry * entry, const char *name) const headerMangler * HeaderManglers::track(const char *name) { - Http::HdrType id = Http::HeaderLookupTable.lookup(SBuf(name)); + if (strcmp(name, "All") == 0) + return &all; - if (id == Http::HdrType::BAD_HDR) { // special keyword or a custom header - if (strcmp(name, "All") == 0) - id = Http::HdrType::ENUM_END; - else if (strcmp(name, "Other") == 0) - id = Http::HdrType::OTHER; - } + const Http::HdrType id = Http::HeaderLookupTable.lookup(SBuf(name)).id; - headerMangler *m = NULL; - if (id == Http::HdrType::ENUM_END) { - m = &all; - } else if (id == Http::HdrType::BAD_HDR) { - m = &custom[name]; - } else { - m = &known[id]; // including Http::HdrType::OTHER - } + if (id != Http::HdrType::BAD_HDR) + return &known[id]; + + if (strcmp(name, "Other") == 0) + return &known[Http::HdrType::OTHER]; - assert(m); - return m; + return &custom[name]; } void diff --git a/src/HttpHeaderTools.h b/src/HttpHeaderTools.h index fd1940dcbb..69375748e5 100644 --- a/src/HttpHeaderTools.h +++ b/src/HttpHeaderTools.h @@ -73,7 +73,7 @@ private: typedef std::map ManglersByName; /// one mangler for each known header - headerMangler known[static_cast(Http::HdrType::ENUM_END)]; + headerMangler known[static_cast(Http::HdrType::enumEnd_)]; /// one mangler for each custom header ManglersByName custom; diff --git a/src/HttpReply.cc b/src/HttpReply.cc index bfeaedf847..dfd64d29e6 100644 --- a/src/HttpReply.cc +++ b/src/HttpReply.cc @@ -11,6 +11,7 @@ #include "squid.h" #include "acl/AclSizeLimit.h" #include "acl/FilledChecklist.h" +#include "base/EnumIterator.h" #include "globals.h" #include "HttpBody.h" #include "HttpHdrCc.h" @@ -38,16 +39,11 @@ * The list of headers we don't update is made up of: * all hop-by-hop headers * all entity-headers except Expires and Content-Location + * + * These headers are now stored in RegisteredHeadersHash.gperf and accessible + * as Http::HeaderLookupTable.lookup(id).denied304 */ static HttpHeaderMask Denied304HeadersMask; -static Http::HdrType Denied304HeadersArr[] = { - // hop-by-hop headers - Http::HdrType::CONNECTION, Http::HdrType::KEEP_ALIVE, Http::HdrType::PROXY_AUTHENTICATE, Http::HdrType::PROXY_AUTHORIZATION, - Http::HdrType::TE, Http::HdrType::TRAILER, Http::HdrType::TRANSFER_ENCODING, Http::HdrType::UPGRADE, - // entity headers - Http::HdrType::ALLOW, Http::HdrType::CONTENT_ENCODING, Http::HdrType::CONTENT_LANGUAGE, Http::HdrType::CONTENT_LENGTH, - Http::HdrType::CONTENT_MD5, Http::HdrType::CONTENT_RANGE, Http::HdrType::CONTENT_TYPE, Http::HdrType::LAST_MODIFIED -}; /* module initialization */ void @@ -55,7 +51,11 @@ httpReplyInitModule(void) { assert(Http::scNone == 0); // HttpReply::parse() interface assumes that httpHeaderMaskInit(&Denied304HeadersMask, 0); - httpHeaderCalcMask(&Denied304HeadersMask, Denied304HeadersArr, countof(Denied304HeadersArr)); + + for (auto id : WholeEnum()) { + if (Http::HeaderLookupTable.lookup(id).denied304) + CBIT_SET(Denied304HeadersMask, id); + } } HttpReply::HttpReply() : HttpMsg(hoReply), date (0), last_modified (0), @@ -151,9 +151,10 @@ HttpReply::make304() const /* rv->keep_alive */ rv->sline.set(Http::ProtocolVersion(), Http::scNotModified, NULL); - for (t = 0; ImsEntries[t] != Http::HdrType::OTHER; ++t) + for (t = 0; ImsEntries[t] != Http::HdrType::OTHER; ++t) { if ((e = header.findEntry(ImsEntries[t]))) rv->header.addEntry(e->clone()); + } /* rv->body */ return rv; diff --git a/src/ICP.h b/src/ICP.h index 06658734c9..e9734d4cb7 100644 --- a/src/ICP.h +++ b/src/ICP.h @@ -60,14 +60,6 @@ typedef struct _icp_common_t icp_common_t; #ifdef __cplusplus -/// \ingroup ServerProtocolICPAPI -inline icp_opcode & operator++ (icp_opcode & aCode) -{ - int tmp = (int) aCode; - aCode = (icp_opcode) (++tmp); - return aCode; -} - /** \ingroup ServerProtocolICPAPI \todo mempool this diff --git a/src/Makefile.am b/src/Makefile.am index 8593d17efa..eb67da24d6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -421,6 +421,8 @@ squid_SOURCES = \ send-announce.h \ send-announce.cc \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ SBufDetailedStats.cc \ SBufStatsAction.h \ @@ -944,6 +946,7 @@ TESTS += $(check_PROGRAMS) # X.h \ # X.cc #nodist_tests_testX_SOURCES=\ +# tests/stubs_as_needed.cc\ # $(TESTSOURCES) #tests_testX_LDFLAGS = $(LIBADD_DL) #tests_testX_LDADD=\ @@ -996,6 +999,8 @@ tests_testHttpReply_SOURCES=\ SquidString.h \ SquidTime.h \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ String.cc \ @@ -1108,6 +1113,8 @@ tests_testACLMaxUserIP_SOURCES= \ tests/stub_StatHist.cc \ stmem.cc \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ String.cc \ @@ -1377,6 +1384,8 @@ tests_testCacheManager_SOURCES = \ refresh.cc \ RemovalPolicy.cc \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ $(SNMP_SOURCE) \ @@ -1549,6 +1558,8 @@ tests_testDiskIO_SOURCES = \ tests/stub_StatHist.cc \ stmem.cc \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ StoreFileSystem.cc \ @@ -1814,6 +1825,8 @@ tests_testEvent_SOURCES = \ StrList.h \ StrList.cc \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ $(SNMP_SOURCE) \ @@ -2055,6 +2068,8 @@ tests_testEventLoop_SOURCES = \ refresh.h \ refresh.cc \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ $(SNMP_SOURCE) \ @@ -2294,6 +2309,8 @@ tests_test_http_range_SOURCES = \ refresh.cc \ RemovalPolicy.cc \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ $(SNMP_SOURCE) \ @@ -2440,6 +2457,8 @@ tests_testHttp1Parser_SOURCES = \ cache_cf.h \ YesNoNone.h \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ tests/stub_SBufDetailedStats.cc \ tests/stub_cache_cf.cc \ tests/stub_cache_manager.cc \ @@ -2617,6 +2636,8 @@ tests_testHttpRequest_SOURCES = \ refresh.cc \ RemovalPolicy.cc \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ $(SNMP_SOURCE) \ @@ -2828,6 +2849,8 @@ tests_testStore_SOURCES= \ store_key_md5.h \ store_key_md5.cc \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ String.cc \ @@ -3073,6 +3096,8 @@ tests_testUfs_SOURCES = \ tests/stub_helper.cc \ cbdata.cc \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ String.cc \ @@ -3251,6 +3276,8 @@ tests_testRock_SOURCES = \ store_swapmeta.cc \ store_swapout.cc \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ String.cc \ @@ -3468,6 +3495,8 @@ tests_testURL_SOURCES = \ refresh.cc \ RemovalPolicy.cc \ $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ $(SNMP_SOURCE) \ @@ -3762,7 +3791,9 @@ tests_testLookupTable_SOURCES = \ tests/stub_SBufDetailedStats.cc \ base/LookupTable.h \ String.cc \ - $(SBUF_SOURCE) + $(SBUF_SOURCE) \ + SBufAlgos.h \ + SBufAlgos.cc nodist_tests_testLookupTable_SOURCES = $(TESTSOURCES) tests_testLookupTable_LDFLAGS = $(LIBADD_DL) tests_testLookupTable_LDADD = \ diff --git a/src/acl/HttpHeaderData.cc b/src/acl/HttpHeaderData.cc index 632b461ca3..4660d5d1a3 100644 --- a/src/acl/HttpHeaderData.cc +++ b/src/acl/HttpHeaderData.cc @@ -47,7 +47,7 @@ ACLHTTPHeaderData::match(HttpHeader* hdr) return false; value = hdr->getStrOrList(hdrId); } else { - if (!hdr->getByNameIfPresent(hdrName.termedBuf(), value)) + if (!hdr->getByNameIfPresent(hdrName, value)) return false; } @@ -76,14 +76,14 @@ ACLHTTPHeaderData::parse() char* t = ConfigParser::strtokFile(); assert (t != NULL); hdrName = t; - hdrId = Http::HeaderLookupTable.lookup(SBuf(hdrName)); + hdrId = Http::HeaderLookupTable.lookup(hdrName).id; regex_rule->parse(); } bool ACLHTTPHeaderData::empty() const { - return (hdrId == Http::HdrType::BAD_HDR && hdrName.size()==0) || regex_rule->empty(); + return (hdrId == Http::HdrType::BAD_HDR && hdrName.isEmpty()) || regex_rule->empty(); } ACLData * diff --git a/src/acl/HttpHeaderData.h b/src/acl/HttpHeaderData.h index b41be27ffa..2f049a77dc 100644 --- a/src/acl/HttpHeaderData.h +++ b/src/acl/HttpHeaderData.h @@ -11,6 +11,7 @@ #include "acl/Data.h" #include "HttpHeader.h" +#include "SBuf.h" #include "SquidString.h" class ACLHTTPHeaderData : public ACLData @@ -27,8 +28,8 @@ public: virtual ACLData *clone() const; private: - Http::HdrType hdrId; /**< set if header is known */ - String hdrName; /**< always set */ + Http::HdrType hdrId; /**< set if header is known */ + SBuf hdrName; /**< always set */ ACLData * regex_rule; }; diff --git a/src/adaptation/icap/ModXact.cc b/src/adaptation/icap/ModXact.cc index 1bba4837dd..5ea70551ec 100644 --- a/src/adaptation/icap/ModXact.cc +++ b/src/adaptation/icap/ModXact.cc @@ -1342,12 +1342,12 @@ void Adaptation::Icap::ModXact::makeRequestHeaders(MemBuf &buf) // we must forward "Proxy-Authenticate" and "Proxy-Authorization" // as ICAP headers. if (virgin.header->header.has(Http::HdrType::PROXY_AUTHENTICATE)) { - String vh=virgin.header->header.getByName("Proxy-Authenticate"); + String vh=virgin.header->header.getById(Http::HdrType::PROXY_AUTHENTICATE); buf.appendf("Proxy-Authenticate: " SQUIDSTRINGPH "\r\n",SQUIDSTRINGPRINT(vh)); } if (virgin.header->header.has(Http::HdrType::PROXY_AUTHORIZATION)) { - String vh=virgin.header->header.getByName("Proxy-Authorization"); + String vh=virgin.header->header.getById(Http::HdrType::PROXY_AUTHORIZATION); buf.appendf("Proxy-Authorization: " SQUIDSTRINGPH "\r\n", SQUIDSTRINGPRINT(vh)); } else if (request->extacl_user.size() > 0 && request->extacl_passwd.size() > 0) { struct base64_encode_ctx ctx; diff --git a/src/auth/UserRequest.cc b/src/auth/UserRequest.cc index 871b24ee70..1ded1096cc 100644 --- a/src/auth/UserRequest.cc +++ b/src/auth/UserRequest.cc @@ -481,11 +481,11 @@ Auth::UserRequest::addReplyAuthHeader(HttpReply * rep, Auth::UserRequest::Pointe default: /* Keep GCC happy */ /* some other HTTP status */ - type = Http::HdrType::ENUM_END; + type = Http::HdrType::BAD_HDR; break; } - debugs(29, 9, HERE << "headertype:" << type << " authuser:" << auth_user_request); + debugs(29, 9, "headertype:" << type << " authuser:" << auth_user_request); if (((rep->sline.status() == Http::scProxyAuthenticationRequired) || (rep->sline.status() == Http::scUnauthorized)) && internal) diff --git a/src/base/LookupTable.h b/src/base/LookupTable.h index 4803644be0..a4be0f23b9 100644 --- a/src/base/LookupTable.h +++ b/src/base/LookupTable.h @@ -10,8 +10,9 @@ #define SQUID_LOOKUPTABLE_H_ #include "SBuf.h" +#include "SBufAlgos.h" -#include +#include /** * a record in the initializer list for a LookupTable @@ -53,7 +54,7 @@ public: } }; -template > +template, typename Hasher = CaseInsensitiveSBufHash > class LookupTable { public: @@ -76,7 +77,7 @@ public: } private: - typedef std::map lookupTable_t; + typedef std::unordered_map lookupTable_t; lookupTable_t lookupTable; EnumType invalidValue; }; diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 3b870684ee..1dc49886cf 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -4609,7 +4609,7 @@ static void parse_HeaderWithAclList(HeaderWithAclList **headers) } HeaderWithAcl hwa; hwa.fieldName = fn; - hwa.fieldId = Http::HeaderLookupTable.lookup(SBuf(fn)); + hwa.fieldId = Http::HeaderLookupTable.lookup(hwa.fieldName).id; if (hwa.fieldId == Http::HdrType::BAD_HDR) hwa.fieldId = Http::HdrType::OTHER; diff --git a/src/client_side_reply.cc b/src/client_side_reply.cc index c90f16ba8d..723e4f231c 100644 --- a/src/client_side_reply.cc +++ b/src/client_side_reply.cc @@ -1353,19 +1353,19 @@ clientReplyContext::buildReplyHeader() */ if (EBIT_TEST(http->storeEntry()->flags, ENTRY_SPECIAL)) { hdr->delById(Http::HdrType::DATE); - hdr->insertTime(Http::HdrType::DATE, squid_curtime); + hdr->putTime(Http::HdrType::DATE, squid_curtime); } else if (http->getConn() && http->getConn()->port->actAsOrigin) { // Swap the Date: header to current time if we are simulating an origin HttpHeaderEntry *h = hdr->findEntry(Http::HdrType::DATE); if (h) hdr->putExt("X-Origin-Date", h->value.termedBuf()); hdr->delById(Http::HdrType::DATE); - hdr->insertTime(Http::HdrType::DATE, squid_curtime); + hdr->putTime(Http::HdrType::DATE, squid_curtime); h = hdr->findEntry(Http::HdrType::EXPIRES); if (h && http->storeEntry()->expires >= 0) { hdr->putExt("X-Origin-Expires", h->value.termedBuf()); hdr->delById(Http::HdrType::EXPIRES); - hdr->insertTime(Http::HdrType::EXPIRES, squid_curtime + http->storeEntry()->expires - http->storeEntry()->timestamp); + hdr->putTime(Http::HdrType::EXPIRES, squid_curtime + http->storeEntry()->expires - http->storeEntry()->timestamp); } if (http->storeEntry()->timestamp <= squid_curtime) { // put X-Cache-Age: instead of Age: @@ -1404,9 +1404,9 @@ clientReplyContext::buildReplyHeader() */ if ( !hdr->has(Http::HdrType::DATE) ) { if (!http->storeEntry()) - hdr->insertTime(Http::HdrType::DATE, squid_curtime); + hdr->putTime(Http::HdrType::DATE, squid_curtime); else if (http->storeEntry()->timestamp > 0) - hdr->insertTime(Http::HdrType::DATE, http->storeEntry()->timestamp); + hdr->putTime(Http::HdrType::DATE, http->storeEntry()->timestamp); else { debugs(88,DBG_IMPORTANT,"BUG 3279: HTTP reply without Date:"); /* dump something useful about the problem */ diff --git a/src/external_acl.cc b/src/external_acl.cc index 70fbd6f247..db22c204b3 100644 --- a/src/external_acl.cc +++ b/src/external_acl.cc @@ -250,7 +250,7 @@ parse_header_token(external_acl_format::Pointer format, char *header, const Form } format->header = xstrdup(header); - format->header_id = Http::HeaderLookupTable.lookup(SBuf(header)); + format->header_id = Http::HeaderLookupTable.lookup(SBuf(header)).id; } void diff --git a/src/htcp.cc b/src/htcp.cc index df6eecbc4c..26a50f82d7 100644 --- a/src/htcp.cc +++ b/src/htcp.cc @@ -853,7 +853,7 @@ htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, Ip::Ad stuff.D.respHdrsSz = mb.contentSize(); debugs(31, 3, "htcpTstReply: resp_hdrs = {" << stuff.D.resp_hdrs << "}"); mb.reset(); - hdr.reset(); + hdr.clean(); if (e && e->expires > -1) hdr.putTime(Http::HdrType::EXPIRES, e->expires); @@ -869,8 +869,7 @@ htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, Ip::Ad debugs(31, 3, "htcpTstReply: entity_hdrs = {" << stuff.D.entity_hdrs << "}"); mb.reset(); - - hdr.reset(); + hdr.clean(); #if USE_ICMP if (char *host = urlHostname(spec->uri)) { diff --git a/src/http.cc b/src/http.cc index 33ea69a334..912bb46768 100644 --- a/src/http.cc +++ b/src/http.cc @@ -589,22 +589,16 @@ httpMakeVaryMark(HttpRequest * request, HttpReply const * reply) vary = reply->header.getList(Http::HdrType::VARY); while (strListGetItem(&vary, ',', &item, &ilen, &pos)) { - char *name = (char *)xmalloc(ilen + 1); - xstrncpy(name, item, ilen + 1); - Tolower(name); - - if (strcmp(name, "*") == 0) { - /* Can not handle "Vary: *" withtout ETag support */ - safe_free(name); + static const SBuf asterisk("*"); + SBuf name(item, ilen); + if (name == asterisk) { vstr.clean(); break; } - - strListAdd(&vstr, name, ','); + name.toLower(); + strListAdd(&vstr, name.c_str(), ','); hdr = request->header.getByName(name); - safe_free(name); value = hdr.termedBuf(); - if (value) { value = rfc1738_escape_part(value); vstr.append("=\"", 2); diff --git a/src/http/Makefile.am b/src/http/Makefile.am index 6561ef67ca..03cff1ef68 100644 --- a/src/http/Makefile.am +++ b/src/http/Makefile.am @@ -20,6 +20,8 @@ libsquid_http_la_SOURCES = \ ProtocolVersion.h \ RegisteredHeaders.h \ RegisteredHeaders.cc \ + RegisteredHeadersHash.cci \ + RegisteredHeadersHash.gperf \ RequestMethod.cc \ RequestMethod.h \ StatusCode.cc \ @@ -33,4 +35,7 @@ MethodType.cc: MethodType.h $(top_srcdir)/src/mk-string-arrays.awk ($(AWK) -f $(top_srcdir)/src/mk-string-arrays.awk sbuf=1 < $(srcdir)/MethodType.h | \ sed -e 's%METHOD_%%' -e 's%_C%-C%' >$@) || ($(RM) -f $@ && exit 1) +RegisteredHeadersHash.cci: RegisteredHeadersHash.gperf + gperf --output-file=$@ -m 100000 $< + CLEANFILES += MethodType.cc diff --git a/src/http/RegisteredHeaders.cc b/src/http/RegisteredHeaders.cc index e8f220f607..349f333731 100644 --- a/src/http/RegisteredHeaders.cc +++ b/src/http/RegisteredHeaders.cc @@ -10,114 +10,60 @@ #include "RegisteredHeaders.h" #include +#include namespace Http { -/* - * A table with major attributes for every known field. - * - * Invariant on this table: - * for each index in HeaderTable, (int)HeaderTable[index] = index - * - * To be kept in sync with Http::HdrType - */ -const HeaderTableRecord HeaderTable[] = { - {"Accept", Http::HdrType::ACCEPT, Http::HdrFieldType::ftStr}, - {"Accept-Charset", Http::HdrType::ACCEPT_CHARSET, Http::HdrFieldType::ftStr}, - {"Accept-Encoding", Http::HdrType::ACCEPT_ENCODING, Http::HdrFieldType::ftStr}, - {"Accept-Language", Http::HdrType::ACCEPT_LANGUAGE, Http::HdrFieldType::ftStr}, - {"Accept-Ranges", Http::HdrType::ACCEPT_RANGES, Http::HdrFieldType::ftStr}, - {"Age", Http::HdrType::AGE, Http::HdrFieldType::ftInt}, - {"Allow", Http::HdrType::ALLOW, Http::HdrFieldType::ftStr}, - {"Alternate-Protocol", Http::HdrType::ALTERNATE_PROTOCOL, Http::HdrFieldType::ftStr}, - {"Authentication-Info", Http::HdrType::AUTHENTICATION_INFO, Http::HdrFieldType::ftStr}, - {"Authorization", Http::HdrType::AUTHORIZATION, Http::HdrFieldType::ftStr}, /* for now */ - {"Cache-Control", Http::HdrType::CACHE_CONTROL, Http::HdrFieldType::ftPCc}, - {"Connection", Http::HdrType::CONNECTION, Http::HdrFieldType::ftStr}, - {"Content-Base", Http::HdrType::CONTENT_BASE, Http::HdrFieldType::ftStr}, - {"Content-Disposition", Http::HdrType::CONTENT_DISPOSITION, Http::HdrFieldType::ftStr}, /* for now */ - {"Content-Encoding", Http::HdrType::CONTENT_ENCODING, Http::HdrFieldType::ftStr}, - {"Content-Language", Http::HdrType::CONTENT_LANGUAGE, Http::HdrFieldType::ftStr}, - {"Content-Length", Http::HdrType::CONTENT_LENGTH, Http::HdrFieldType::ftInt64}, - {"Content-Location", Http::HdrType::CONTENT_LOCATION, Http::HdrFieldType::ftStr}, - {"Content-MD5", Http::HdrType::CONTENT_MD5, Http::HdrFieldType::ftStr}, /* for now */ - {"Content-Range", Http::HdrType::CONTENT_RANGE, Http::HdrFieldType::ftPContRange}, - {"Content-Type", Http::HdrType::CONTENT_TYPE, Http::HdrFieldType::ftStr}, - {"Cookie", Http::HdrType::COOKIE, Http::HdrFieldType::ftStr}, - {"Cookie2", Http::HdrType::COOKIE2, Http::HdrFieldType::ftStr}, - {"Date", Http::HdrType::DATE, Http::HdrFieldType::ftDate_1123}, - {"ETag", Http::HdrType::ETAG, Http::HdrFieldType::ftETag}, - {"Expect", Http::HdrType::EXPECT, Http::HdrFieldType::ftStr}, - {"Expires", Http::HdrType::EXPIRES, Http::HdrFieldType::ftDate_1123}, - {"Forwarded", Http::HdrType::FORWARDED, Http::HdrFieldType::ftStr}, - {"From", Http::HdrType::FROM, Http::HdrFieldType::ftStr}, - {"Host", Http::HdrType::HOST, Http::HdrFieldType::ftStr}, - {"HTTP2-Settings", Http::HdrType::HTTP2_SETTINGS, Http::HdrFieldType::ftStr}, /* for now */ - {"If-Match", Http::HdrType::IF_MATCH, Http::HdrFieldType::ftStr}, /* for now */ - {"If-Modified-Since", Http::HdrType::IF_MODIFIED_SINCE, Http::HdrFieldType::ftDate_1123}, - {"If-None-Match", Http::HdrType::IF_NONE_MATCH, Http::HdrFieldType::ftStr}, /* for now */ - {"If-Range", Http::HdrType::IF_RANGE, Http::HdrFieldType::ftDate_1123_or_ETag}, - {"If-Unmodified-Since", Http::HdrType::IF_UNMODIFIED_SINCE, Http::HdrFieldType::ftDate_1123}, - {"Keep-Alive", Http::HdrType::KEEP_ALIVE, Http::HdrFieldType::ftStr}, - {"Key", Http::HdrType::KEY, Http::HdrFieldType::ftStr}, - {"Last-Modified", Http::HdrType::LAST_MODIFIED, Http::HdrFieldType::ftDate_1123}, - {"Link", Http::HdrType::LINK, Http::HdrFieldType::ftStr}, - {"Location", Http::HdrType::LOCATION, Http::HdrFieldType::ftStr}, - {"Max-Forwards", Http::HdrType::MAX_FORWARDS, Http::HdrFieldType::ftInt64}, - {"Mime-Version", Http::HdrType::MIME_VERSION, Http::HdrFieldType::ftStr}, /* for now */ - {"Negotiate", Http::HdrType::NEGOTIATE, Http::HdrFieldType::ftStr}, - {"Origin", Http::HdrType::ORIGIN, Http::HdrFieldType::ftStr}, - {"Pragma", Http::HdrType::PRAGMA, Http::HdrFieldType::ftStr}, - {"Proxy-Authenticate", Http::HdrType::PROXY_AUTHENTICATE, Http::HdrFieldType::ftStr}, - {"Proxy-Authentication-Info", Http::HdrType::PROXY_AUTHENTICATION_INFO, Http::HdrFieldType::ftStr}, - {"Proxy-Authorization", Http::HdrType::PROXY_AUTHORIZATION, Http::HdrFieldType::ftStr}, - {"Proxy-Connection", Http::HdrType::PROXY_CONNECTION, Http::HdrFieldType::ftStr}, - {"Proxy-support", Http::HdrType::PROXY_SUPPORT, Http::HdrFieldType::ftStr}, - {"Public", Http::HdrType::PUBLIC, Http::HdrFieldType::ftStr}, - {"Range", Http::HdrType::RANGE, Http::HdrFieldType::ftPRange}, - {"Referer", Http::HdrType::REFERER, Http::HdrFieldType::ftStr}, - {"Request-Range", Http::HdrType::REQUEST_RANGE, Http::HdrFieldType::ftPRange}, /* usually matches Http::HdrType::RANGE */ - {"Retry-After", Http::HdrType::RETRY_AFTER, Http::HdrFieldType::ftStr}, /* for now (Http::HdrFieldType::ftDate_1123 or Http::HdrFieldType::ftInt!} */ - {"Server", Http::HdrType::SERVER, Http::HdrFieldType::ftStr}, - {"Set-Cookie", Http::HdrType::SET_COOKIE, Http::HdrFieldType::ftStr}, - {"Set-Cookie2", Http::HdrType::SET_COOKIE2, Http::HdrFieldType::ftStr}, - {"TE", Http::HdrType::TE, Http::HdrFieldType::ftStr}, - {"Title", Http::HdrType::TITLE, Http::HdrFieldType::ftStr}, - {"Trailer", Http::HdrType::TRAILER, Http::HdrFieldType::ftStr}, - {"Transfer-Encoding", Http::HdrType::TRANSFER_ENCODING, Http::HdrFieldType::ftStr}, - {"Translate", Http::HdrType::TRANSLATE, Http::HdrFieldType::ftStr}, /* for now. may need to crop */ - {"Unless-Modified-Since", Http::HdrType::UNLESS_MODIFIED_SINCE, Http::HdrFieldType::ftStr}, /* for now ignore. may need to crop */ - {"Upgrade", Http::HdrType::UPGRADE, Http::HdrFieldType::ftStr}, /* for now */ - {"User-Agent", Http::HdrType::USER_AGENT, Http::HdrFieldType::ftStr}, - {"Vary", Http::HdrType::VARY, Http::HdrFieldType::ftStr}, /* for now */ - {"Via", Http::HdrType::VIA, Http::HdrFieldType::ftStr}, /* for now */ - {"Warning", Http::HdrType::WARNING, Http::HdrFieldType::ftStr}, /* for now */ - {"WWW-Authenticate", Http::HdrType::WWW_AUTHENTICATE, Http::HdrFieldType::ftStr}, - {"X-Cache", Http::HdrType::X_CACHE, Http::HdrFieldType::ftStr}, - {"X-Cache-Lookup", Http::HdrType::X_CACHE_LOOKUP, Http::HdrFieldType::ftStr}, - {"X-Forwarded-For", Http::HdrType::X_FORWARDED_FOR, Http::HdrFieldType::ftStr}, - {"X-Request-URI", Http::HdrType::X_REQUEST_URI, Http::HdrFieldType::ftStr}, - {"X-Squid-Error", Http::HdrType::X_SQUID_ERROR, Http::HdrFieldType::ftStr}, -#if X_ACCELERATOR_VARY - {"X-Accelerator-Vary", Http::HdrType::HDR_X_ACCELERATOR_VARY, Http::HdrFieldType::ftStr}, -#endif -#if USE_ADAPTATION - {"X-Next-Services", Http::HdrType::X_NEXT_SERVICES, Http::HdrFieldType::ftStr}, -#endif - {"Surrogate-Capability", Http::HdrType::SURROGATE_CAPABILITY, Http::HdrFieldType::ftStr}, - {"Surrogate-Control", Http::HdrType::SURROGATE_CONTROL, Http::HdrFieldType::ftPSc}, - {"Front-End-Https", Http::HdrType::FRONT_END_HTTPS, Http::HdrFieldType::ftStr}, - {"FTP-Command", Http::HdrType::FTP_COMMAND, Http::HdrFieldType::ftStr}, - {"FTP-Arguments", Http::HdrType::FTP_ARGUMENTS, Http::HdrFieldType::ftStr}, - {"FTP-Pre", Http::HdrType::FTP_PRE, Http::HdrFieldType::ftStr}, - {"FTP-Status", Http::HdrType::FTP_STATUS, Http::HdrFieldType::ftInt}, - {"FTP-Reason", Http::HdrType::FTP_REASON, Http::HdrFieldType::ftStr}, - {"Other:", Http::HdrType::OTHER, Http::HdrFieldType::ftStr}, /* ':' will not allow matches */ - {"*INVALID*:", Http::HdrType::BAD_HDR, Http::HdrFieldType::ftInvalid}, /* ':' will not allow matches */ - {nullptr, Http::HdrType::ENUM_END, Http::HdrFieldType::ftInvalid} /* end of table */ -}; +/* glue to code generated by gperf */ +#include "http/RegisteredHeadersHash.cci" + +HeaderTableRecord::HeaderTableRecord() : + name(""), id(HdrType::BAD_HDR),type(HdrFieldType::ftInvalid), + list(false), request(false), reply(false), hopbyhop(false) +{} + +HeaderTableRecord::HeaderTableRecord(const char *n) : + name(n), id(HdrType::BAD_HDR), type(HdrFieldType::ftInvalid), + list(false), request(false), reply(false), hopbyhop(false) +{} + +HeaderTableRecord::HeaderTableRecord(const char *n, HdrType theId, HdrFieldType theType, int theKind) : + name(n), id(theId), type(theType), + list(theKind & HdrKind::ListHeader), request(theKind & HdrKind::RequestHeader), + reply(theKind & HdrKind::ReplyHeader), hopbyhop(theKind & HdrKind::HopByHopHeader), + denied304(theKind & HdrKind::Denied304Header) +{} -const LookupTable HeaderLookupTable(Http::HdrType::BAD_HDR, HeaderTable); +const HeaderTableRecord& +HeaderLookupTable_t::lookup (const char *buf, const std::size_t len) const { + const HeaderTableRecord *r = HttpHeaderHashTable::lookup(buf, len); + if (!r) + return BadHdr; + return *r; +} +const HeaderTableRecord HeaderLookupTable_t::BadHdr {"*INVALID*:", Http::HdrType::BAD_HDR, Http::HdrFieldType::ftInvalid, HdrKind::None}; + +HeaderLookupTable_t::HeaderLookupTable_t() +{ + initCache(); +} + +void +HeaderLookupTable_t::initCache() +{ + idCache.resize(TOTAL_KEYWORDS); + for (int j = MIN_HASH_VALUE; j <= MAX_HASH_VALUE; ++j) { //MAX_HASH_VALUE is exported by gperf + if (HttpHeaderDefinitionsTable[j].name[0] != '\0') { //some slots are empty + idCache[static_cast(HttpHeaderDefinitionsTable[j].id)] = + & HttpHeaderDefinitionsTable[j]; + } + } + //check after the fact. The cache array must be full + for (auto e : idCache) { + assert(e->name); + } +} +const HeaderLookupTable_t HeaderLookupTable; }; /* namespace Http */ @@ -125,7 +71,7 @@ std::ostream& operator<< (std::ostream &s, Http::HdrType id) { if (Http::any_HdrType_enum_value(id)) - s << Http::HeaderTable[id].name << '[' << static_cast(id) << ']'; + s << Http::HeaderLookupTable.lookup(id).name << '[' << static_cast(id) << ']'; else s << "Invalid-Header[" << static_cast(id) << ']'; return s; diff --git a/src/http/RegisteredHeaders.h b/src/http/RegisteredHeaders.h index 3c4f2febde..5bab8ce780 100644 --- a/src/http/RegisteredHeaders.h +++ b/src/http/RegisteredHeaders.h @@ -17,7 +17,8 @@ namespace Http /// recognized or "known" header fields; and the RFC which defines them (or not) /// http://www.iana.org/assignments/message-headers/message-headers.xhtml enum HdrType { - ACCEPT = 0, /**< RFC 7231 */ /* MUST BE FIRST */ + enumBegin_ = 0, // service value for WholeEnum iteration + ACCEPT = enumBegin_, /**< RFC 7231 */ /* MUST BE FIRST */ ACCEPT_CHARSET, /**< RFC 7231 */ ACCEPT_ENCODING, /**< RFC 7231 */ /*ACCEPT_FEATURES,*/ /* RFC 2295 */ @@ -105,12 +106,8 @@ enum HdrType { X_FORWARDED_FOR, /**< obsolete Squid custom header, RFC 7239 */ X_REQUEST_URI, /**< Squid custom header appended if ADD_X_REQUEST_URI is defined */ X_SQUID_ERROR, /**< Squid custom header on generated error responses */ -#if X_ACCELERATOR_VARY HDR_X_ACCELERATOR_VARY, /**< obsolete Squid custom header. */ -#endif -#if USE_ADAPTATION X_NEXT_SERVICES, /**< Squid custom ICAP header */ -#endif SURROGATE_CAPABILITY, /**< Edge Side Includes (ESI) header */ SURROGATE_CONTROL, /**< Edge Side Includes (ESI) header */ FRONT_END_HTTPS, /**< MS Exchange custom header we may have to add */ @@ -120,8 +117,8 @@ enum HdrType { FTP_STATUS, /**< Internal header for FTP reply status */ FTP_REASON, /**< Internal header for FTP reply reason */ OTHER, /**< internal tag value for "unknown" headers */ - BAD_HDR, /**< Invalid header. Must be after ENUM_END */ - ENUM_END /**< internal tag for end-of-headers */ + BAD_HDR, /**< Invalid header */ + enumEnd_ // internal tag for end-of-headers }; /** possible types for http header fields */ @@ -139,31 +136,74 @@ enum class HdrFieldType { ftDate_1123_or_ETag }; +enum HdrKind { + None = 0, + ListHeader = 1, + RequestHeader = 1 << 1, + ReplyHeader = 1 << 2, + HopByHopHeader = 1 << 3, + Denied304Header = 1 << 4, //see comment in HttpReply.cc for meaning + GeneralHeader = RequestHeader | ReplyHeader, + EntityHeader = RequestHeader | ReplyHeader +}; + /* POD for HeaderTable */ class HeaderTableRecord { +public: + HeaderTableRecord(); + HeaderTableRecord(const char *n); + HeaderTableRecord(const char *, Http::HdrType, Http::HdrFieldType, int /* HdrKind */); + public: const char *name; Http::HdrType id; Http::HdrFieldType type; + // flags set by constructor from HdrKind parameter + bool list; ///
namelookup table. -extern const HeaderTableRecord HeaderTable[]; - -/** LookupTable for HTTP Header name -> Http::HdrType lookup. +/** Class for looking up registered header definitions * - * use as HeaderLookupTable.lookup(header-as-sbuf). - * It will return Http::HdrType::HDR_BAD if the header is unknown/not registered, - * including the case of Http::HdrType::OTHER, which will have to be handled - * by the caller. + * Look up HeaderTableRecord's by name or registered header ID. + * + * Actual records are defined in file RegisteredHeadersHash.gperf, which is + * compiled using gperf to RegisteredHeadersHash.cci which is then included + * in RegisteredHeaders.cc. */ -extern const LookupTable HeaderLookupTable; +class HeaderLookupTable_t { +public: + HeaderLookupTable_t(); + /// look record type up by name (C-string and length) + const HeaderTableRecord& lookup (const char *buf, const std::size_t len) const; + /// look record type up by name (std::string) + const HeaderTableRecord& lookup (const std::string &key) const { + return lookup(key.data(), key.length()); + } + /// look record type up by name (SBuf) + const HeaderTableRecord& lookup (const SBuf &key) const { + return lookup(key.rawContent(), key.length()); + } + /// look record type up by header ID + const HeaderTableRecord& lookup (Http::HdrType id) const { + return *(idCache[static_cast(id)]); + } + +private: + void initCache(); + std::vector idCache; + static const HeaderTableRecord BadHdr; ///= Http::HdrType::ACCEPT && id < Http::HdrType::ENUM_END); + return (id >= Http::HdrType::enumBegin_ && id < Http::HdrType::enumEnd_); } /// match any valid header type, including OTHER but not BAD diff --git a/src/http/RegisteredHeadersHash.cci b/src/http/RegisteredHeadersHash.cci new file mode 100644 index 0000000000..a7ec442fa1 --- /dev/null +++ b/src/http/RegisteredHeadersHash.cci @@ -0,0 +1,381 @@ +/* C++ code produced by gperf version 3.0.4 */ +/* Command-line: gperf --output-file=RegisteredHeadersHash.cci -m 100000 RegisteredHeadersHash.gperf */ +/* Computed positions: -k'1,9,$' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 1 "RegisteredHeadersHash.gperf" + +/* AUTO GENERATED FROM RegisteredHeadersHash.gperf. DO NOT EDIT */ + +/* + * Copyright (C) 1996-2015 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ +#line 24 "RegisteredHeadersHash.gperf" +struct HeaderTableRecord; +enum + { + TOTAL_KEYWORDS = 88, + MIN_WORD_LENGTH = 2, + MAX_WORD_LENGTH = 25, + MIN_HASH_VALUE = 7, + MAX_HASH_VALUE = 113 + }; + +/* maximum key range = 107, duplicates = 0 */ + +#ifndef GPERF_DOWNCASE +#define GPERF_DOWNCASE 1 +static unsigned char gperf_downcase[256] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255 + }; +#endif + +#ifndef GPERF_CASE_MEMCMP +#define GPERF_CASE_MEMCMP 1 +static int +gperf_case_memcmp (register const char *s1, register const char *s2, register unsigned int n) +{ + for (; n > 0;) + { + unsigned char c1 = gperf_downcase[(unsigned char)*s1++]; + unsigned char c2 = gperf_downcase[(unsigned char)*s2++]; + if (c1 == c2) + { + n--; + continue; + } + return (int)c1 - (int)c2; + } + return 0; +} +#endif + +class HttpHeaderHashTable +{ +private: + static inline unsigned int HttpHeaderHash (const char *str, unsigned int len); +public: + static const struct HeaderTableRecord *lookup (const char *str, unsigned int len); +}; + +inline unsigned int +HttpHeaderHashTable::HttpHeaderHash (register const char *str, register unsigned int len) +{ + static const unsigned char asso_values[] = + { + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 14, 114, 114, 5, 114, 114, 114, 114, + 64, 114, 114, 14, 114, 114, 114, 114, 1, 114, + 114, 114, 114, 114, 114, 4, 5, 15, 29, 1, + 17, 60, 35, 19, 114, 51, 15, 42, 8, 50, + 11, 114, 1, 19, 7, 28, 4, 41, 33, 15, + 114, 114, 114, 114, 114, 114, 114, 4, 5, 15, + 29, 1, 17, 60, 35, 19, 114, 51, 15, 42, + 8, 50, 11, 114, 1, 19, 7, 28, 4, 41, + 33, 15, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[8]]; + /*FALLTHROUGH*/ + case 8: + case 7: + case 6: + case 5: + case 4: + case 3: + case 2: + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval + asso_values[(unsigned char)str[len - 1]]; +} + +static const unsigned char lengthtable[] = + { + 0, 0, 0, 0, 0, 0, 0, 5, 3, 7, 2, 3, 0, 5, + 6, 7, 13, 6, 9, 9, 11, 6, 6, 4, 15, 7, 6, 7, + 8, 13, 13, 8, 6, 12, 4, 12, 7, 18, 18, 10, 13, 7, + 13, 16, 0, 19, 4, 16, 13, 10, 5, 13, 17, 10, 16, 20, + 17, 6, 19, 16, 14, 11, 8, 4, 6, 4, 10, 18, 15, 3, + 4, 19, 13, 14, 10, 14, 13, 12, 15, 14, 15, 12, 11, 10, + 9, 10, 7, 15, 19, 17, 0, 13, 16, 25, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 7, 13, 0, 0, + 0, 11 + }; + +static const struct HeaderTableRecord HttpHeaderDefinitionsTable[] = + { + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 78 "RegisteredHeadersHash.gperf" + {"Range", Http::HdrType::RANGE, Http::HdrFieldType::ftPRange, HdrKind::RequestHeader}, +#line 31 "RegisteredHeadersHash.gperf" + {"Age", Http::HdrType::AGE, Http::HdrFieldType::ftInt, HdrKind::ReplyHeader}, +#line 79 "RegisteredHeadersHash.gperf" + {"Referer", Http::HdrType::REFERER, Http::HdrFieldType::ftStr, HdrKind::RequestHeader}, +#line 85 "RegisteredHeadersHash.gperf" + {"TE", Http::HdrType::TE, Http::HdrFieldType::ftStr, HdrKind::RequestHeader|HdrKind::HopByHopHeader|HdrKind::Denied304Header}, +#line 94 "RegisteredHeadersHash.gperf" + {"Via", Http::HdrType::VIA, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader}, + {""}, +#line 86 "RegisteredHeadersHash.gperf" + {"Title", Http::HdrType::TITLE, Http::HdrFieldType::ftStr, HdrKind::None}, +#line 51 "RegisteredHeadersHash.gperf" + {"Expect", Http::HdrType::EXPECT, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader}, +#line 87 "RegisteredHeadersHash.gperf" + {"Trailer", Http::HdrType::TRAILER, Http::HdrFieldType::ftStr, HdrKind::HopByHopHeader|HdrKind::Denied304Header}, +#line 80 "RegisteredHeadersHash.gperf" + {"Request-Range", Http::HdrType::REQUEST_RANGE, Http::HdrFieldType::ftPRange, HdrKind::None}, +#line 26 "RegisteredHeadersHash.gperf" + {"Accept", Http::HdrType::ACCEPT, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader}, +#line 89 "RegisteredHeadersHash.gperf" + {"Translate", Http::HdrType::TRANSLATE, Http::HdrFieldType::ftStr, HdrKind::None}, +#line 69 "RegisteredHeadersHash.gperf" + {"Negotiate", Http::HdrType::NEGOTIATE, Http::HdrFieldType::ftStr, HdrKind::None}, +#line 81 "RegisteredHeadersHash.gperf" + {"Retry-After", Http::HdrType::RETRY_AFTER, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader}, +#line 71 "RegisteredHeadersHash.gperf" + {"Pragma", Http::HdrType::PRAGMA, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader}, +#line 47 "RegisteredHeadersHash.gperf" + {"Cookie", Http::HdrType::COOKIE, Http::HdrFieldType::ftStr, HdrKind::None}, +#line 93 "RegisteredHeadersHash.gperf" + {"Vary", Http::HdrType::VARY, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader}, +#line 29 "RegisteredHeadersHash.gperf" + {"Accept-Language", Http::HdrType::ACCEPT_LANGUAGE, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader}, +#line 109 "RegisteredHeadersHash.gperf" + {"FTP-Pre", Http::HdrType::FTP_PRE, Http::HdrFieldType::ftStr, HdrKind::None}, +#line 82 "RegisteredHeadersHash.gperf" + {"Server", Http::HdrType::SERVER, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader}, +#line 52 "RegisteredHeadersHash.gperf" + {"Expires", Http::HdrType::EXPIRES, Http::HdrFieldType::ftDate_1123, HdrKind::EntityHeader}, +#line 60 "RegisteredHeadersHash.gperf" + {"If-Range", Http::HdrType::IF_RANGE, Http::HdrFieldType::ftDate_1123_or_ETag, HdrKind::None}, +#line 35 "RegisteredHeadersHash.gperf" + {"Authorization", Http::HdrType::AUTHORIZATION, Http::HdrFieldType::ftStr, HdrKind::RequestHeader}, +#line 45 "RegisteredHeadersHash.gperf" + {"Content-Range", Http::HdrType::CONTENT_RANGE, Http::HdrFieldType::ftPContRange, HdrKind::EntityHeader|HdrKind::Denied304Header}, +#line 66 "RegisteredHeadersHash.gperf" + {"Location", Http::HdrType::LOCATION, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader}, +#line 77 "RegisteredHeadersHash.gperf" + {"Public", Http::HdrType::PUBLIC, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader}, +#line 38 "RegisteredHeadersHash.gperf" + {"Content-Base", Http::HdrType::CONTENT_BASE, Http::HdrFieldType::ftStr, HdrKind::EntityHeader}, +#line 49 "RegisteredHeadersHash.gperf" + {"Date", Http::HdrType::DATE, Http::HdrFieldType::ftDate_1123, HdrKind::GeneralHeader}, +#line 46 "RegisteredHeadersHash.gperf" + {"Content-Type", Http::HdrType::CONTENT_TYPE, Http::HdrFieldType::ftStr, HdrKind::EntityHeader|HdrKind::Denied304Header}, +#line 91 "RegisteredHeadersHash.gperf" + {"Upgrade", Http::HdrType::UPGRADE, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader|HdrKind::HopByHopHeader|HdrKind::Denied304Header}, +#line 72 "RegisteredHeadersHash.gperf" + {"Proxy-Authenticate", Http::HdrType::PROXY_AUTHENTICATE, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader|HdrKind::Denied304Header}, +#line 33 "RegisteredHeadersHash.gperf" + {"Alternate-Protocol", Http::HdrType::ALTERNATE_PROTOCOL, Http::HdrFieldType::ftStr, HdrKind::HopByHopHeader}, +#line 113 "RegisteredHeadersHash.gperf" + {"*INVALID*:", Http::HdrType::BAD_HDR, Http::HdrFieldType::ftInvalid, HdrKind::None}, +#line 30 "RegisteredHeadersHash.gperf" + {"Accept-Ranges", Http::HdrType::ACCEPT_RANGES, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader}, +#line 97 "RegisteredHeadersHash.gperf" + {"X-Cache", Http::HdrType::X_CACHE, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader}, +#line 76 "RegisteredHeadersHash.gperf" + {"Proxy-support", Http::HdrType::PROXY_SUPPORT, Http::HdrFieldType::ftStr, HdrKind::ListHeader}, +#line 75 "RegisteredHeadersHash.gperf" + {"Proxy-Connection", Http::HdrType::PROXY_CONNECTION, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader|HdrKind::HopByHopHeader}, + {""}, +#line 74 "RegisteredHeadersHash.gperf" + {"Proxy-Authorization", Http::HdrType::PROXY_AUTHORIZATION, Http::HdrFieldType::ftStr, HdrKind::RequestHeader|HdrKind::HopByHopHeader|HdrKind::Denied304Header}, +#line 55 "RegisteredHeadersHash.gperf" + {"Host", Http::HdrType::HOST, Http::HdrFieldType::ftStr, HdrKind::RequestHeader}, +#line 41 "RegisteredHeadersHash.gperf" + {"Content-Language", Http::HdrType::CONTENT_LANGUAGE, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::EntityHeader|HdrKind::Denied304Header}, +#line 101 "RegisteredHeadersHash.gperf" + {"X-Squid-Error", Http::HdrType::X_SQUID_ERROR, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader}, +#line 83 "RegisteredHeadersHash.gperf" + {"Set-Cookie", Http::HdrType::SET_COOKIE, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader}, +#line 32 "RegisteredHeadersHash.gperf" + {"Allow", Http::HdrType::ALLOW, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::EntityHeader|HdrKind::Denied304Header}, +#line 36 "RegisteredHeadersHash.gperf" + {"Cache-Control", Http::HdrType::CACHE_CONTROL, Http::HdrFieldType::ftPCc, HdrKind::ListHeader|HdrKind::GeneralHeader}, +#line 105 "RegisteredHeadersHash.gperf" + {"Surrogate-Control", Http::HdrType::SURROGATE_CONTROL, Http::HdrFieldType::ftPSc, HdrKind::ListHeader|HdrKind::ReplyHeader}, +#line 92 "RegisteredHeadersHash.gperf" + {"User-Agent", Http::HdrType::USER_AGENT, Http::HdrFieldType::ftStr, HdrKind::RequestHeader}, +#line 43 "RegisteredHeadersHash.gperf" + {"Content-Location", Http::HdrType::CONTENT_LOCATION, Http::HdrFieldType::ftStr, HdrKind::EntityHeader}, +#line 104 "RegisteredHeadersHash.gperf" + {"Surrogate-Capability", Http::HdrType::SURROGATE_CAPABILITY, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader}, +#line 58 "RegisteredHeadersHash.gperf" + {"If-Modified-Since", Http::HdrType::IF_MODIFIED_SINCE, Http::HdrFieldType::ftDate_1123, HdrKind::RequestHeader}, +#line 112 "RegisteredHeadersHash.gperf" + {"Other:", Http::HdrType::OTHER, Http::HdrFieldType::ftStr, HdrKind::EntityHeader}, +#line 61 "RegisteredHeadersHash.gperf" + {"If-Unmodified-Since", Http::HdrType::IF_UNMODIFIED_SINCE, Http::HdrFieldType::ftDate_1123, HdrKind::None}, +#line 96 "RegisteredHeadersHash.gperf" + {"WWW-Authenticate", Http::HdrType::WWW_AUTHENTICATE, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader}, +#line 27 "RegisteredHeadersHash.gperf" + {"Accept-Charset", Http::HdrType::ACCEPT_CHARSET, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader}, +#line 107 "RegisteredHeadersHash.gperf" + {"FTP-Command", Http::HdrType::FTP_COMMAND, Http::HdrFieldType::ftStr, HdrKind::None}, +#line 57 "RegisteredHeadersHash.gperf" + {"If-Match", Http::HdrType::IF_MATCH, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader}, +#line 54 "RegisteredHeadersHash.gperf" + {"From", Http::HdrType::FROM, Http::HdrFieldType::ftStr, HdrKind::RequestHeader}, +#line 70 "RegisteredHeadersHash.gperf" + {"Origin", Http::HdrType::ORIGIN, Http::HdrFieldType::ftStr, HdrKind::RequestHeader}, +#line 50 "RegisteredHeadersHash.gperf" + {"ETag", Http::HdrType::ETAG, Http::HdrFieldType::ftETag, HdrKind::EntityHeader}, +#line 62 "RegisteredHeadersHash.gperf" + {"Keep-Alive", Http::HdrType::KEEP_ALIVE, Http::HdrFieldType::ftStr, HdrKind::HopByHopHeader|HdrKind::Denied304Header}, +#line 102 "RegisteredHeadersHash.gperf" + {"X-Accelerator-Vary", Http::HdrType::HDR_X_ACCELERATOR_VARY, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader}, +#line 103 "RegisteredHeadersHash.gperf" + {"X-Next-Services", Http::HdrType::X_NEXT_SERVICES, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader}, +#line 63 "RegisteredHeadersHash.gperf" + {"Key", Http::HdrType::KEY, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader}, +#line 65 "RegisteredHeadersHash.gperf" + {"Link", Http::HdrType::LINK, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::EntityHeader}, +#line 39 "RegisteredHeadersHash.gperf" + {"Content-Disposition", Http::HdrType::CONTENT_DISPOSITION, Http::HdrFieldType::ftStr, HdrKind::None}, +#line 100 "RegisteredHeadersHash.gperf" + {"X-Request-URI", Http::HdrType::X_REQUEST_URI, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader}, +#line 98 "RegisteredHeadersHash.gperf" + {"X-Cache-Lookup", Http::HdrType::X_CACHE_LOOKUP, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader}, +#line 110 "RegisteredHeadersHash.gperf" + {"FTP-Status", Http::HdrType::FTP_STATUS, Http::HdrFieldType::ftInt, HdrKind::None}, +#line 56 "RegisteredHeadersHash.gperf" + {"HTTP2-Settings", Http::HdrType::HTTP2_SETTINGS, Http::HdrFieldType::ftStr, HdrKind::RequestHeader|HdrKind::HopByHopHeader}, +#line 64 "RegisteredHeadersHash.gperf" + {"Last-Modified", Http::HdrType::LAST_MODIFIED, Http::HdrFieldType::ftDate_1123, HdrKind::EntityHeader|HdrKind::Denied304Header}, +#line 67 "RegisteredHeadersHash.gperf" + {"Max-Forwards", Http::HdrType::MAX_FORWARDS, Http::HdrFieldType::ftInt64, HdrKind::RequestHeader}, +#line 99 "RegisteredHeadersHash.gperf" + {"X-Forwarded-For", Http::HdrType::X_FORWARDED_FOR, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader}, +#line 42 "RegisteredHeadersHash.gperf" + {"Content-Length", Http::HdrType::CONTENT_LENGTH, Http::HdrFieldType::ftInt64, HdrKind::EntityHeader|HdrKind::Denied304Header}, +#line 106 "RegisteredHeadersHash.gperf" + {"Front-End-Https", Http::HdrType::FRONT_END_HTTPS, Http::HdrFieldType::ftStr, HdrKind::None}, +#line 68 "RegisteredHeadersHash.gperf" + {"Mime-Version", Http::HdrType::MIME_VERSION, Http::HdrFieldType::ftStr, HdrKind::GeneralHeader}, +#line 44 "RegisteredHeadersHash.gperf" + {"Content-MD5", Http::HdrType::CONTENT_MD5, Http::HdrFieldType::ftStr, HdrKind::EntityHeader|HdrKind::Denied304Header}, +#line 37 "RegisteredHeadersHash.gperf" + {"Connection", Http::HdrType::CONNECTION, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader|HdrKind::HopByHopHeader|HdrKind::Denied304Header}, +#line 53 "RegisteredHeadersHash.gperf" + {"Forwarded", Http::HdrType::FORWARDED, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader}, +#line 111 "RegisteredHeadersHash.gperf" + {"FTP-Reason", Http::HdrType::FTP_REASON, Http::HdrFieldType::ftStr, HdrKind::None}, +#line 48 "RegisteredHeadersHash.gperf" + {"Cookie2", Http::HdrType::COOKIE2, Http::HdrFieldType::ftStr, HdrKind::None}, +#line 28 "RegisteredHeadersHash.gperf" + {"Accept-Encoding", Http::HdrType::ACCEPT_ENCODING, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader|HdrKind::ReplyHeader}, +#line 34 "RegisteredHeadersHash.gperf" + {"Authentication-Info", Http::HdrType::AUTHENTICATION_INFO, Http::HdrFieldType::ftStr, HdrKind::ListHeader}, +#line 88 "RegisteredHeadersHash.gperf" + {"Transfer-Encoding", Http::HdrType::TRANSFER_ENCODING, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader|HdrKind::HopByHopHeader|HdrKind::Denied304Header}, + {""}, +#line 108 "RegisteredHeadersHash.gperf" + {"FTP-Arguments", Http::HdrType::FTP_ARGUMENTS, Http::HdrFieldType::ftStr, HdrKind::None}, +#line 40 "RegisteredHeadersHash.gperf" + {"Content-Encoding", Http::HdrType::CONTENT_ENCODING, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::EntityHeader|HdrKind::Denied304Header}, +#line 73 "RegisteredHeadersHash.gperf" + {"Proxy-Authentication-Info", Http::HdrType::PROXY_AUTHENTICATION_INFO, Http::HdrFieldType::ftStr, HdrKind::ListHeader}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 90 "RegisteredHeadersHash.gperf" + {"Unless-Modified-Since", Http::HdrType::UNLESS_MODIFIED_SINCE, Http::HdrFieldType::ftStr, HdrKind::None}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 95 "RegisteredHeadersHash.gperf" + {"Warning", Http::HdrType::WARNING, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader}, +#line 59 "RegisteredHeadersHash.gperf" + {"If-None-Match", Http::HdrType::IF_NONE_MATCH, Http::HdrFieldType::ftStr, HdrKind::ListHeader}, + {""}, {""}, {""}, +#line 84 "RegisteredHeadersHash.gperf" + {"Set-Cookie2", Http::HdrType::SET_COOKIE2, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader} + }; + +const struct HeaderTableRecord * +HttpHeaderHashTable::lookup (register const char *str, register unsigned int len) +{ + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = HttpHeaderHash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + if (len == lengthtable[key]) + { + register const char *s = HttpHeaderDefinitionsTable[key].name; + + if ((((unsigned char)*str ^ (unsigned char)*s) & ~32) == 0 && !gperf_case_memcmp (str, s, len)) + return &HttpHeaderDefinitionsTable[key]; + } + } + return 0; +} +#line 114 "RegisteredHeadersHash.gperf" + diff --git a/src/http/RegisteredHeadersHash.gperf b/src/http/RegisteredHeadersHash.gperf new file mode 100644 index 0000000000..c041a5d0ea --- /dev/null +++ b/src/http/RegisteredHeadersHash.gperf @@ -0,0 +1,114 @@ +%{ +/* AUTO GENERATED FROM RegisteredHeadersHash.gperf. DO NOT EDIT */ + +/* + * Copyright (C) 1996-2015 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ +%} +%language=C++ +%define hash-function-name HttpHeaderHash +%define lookup-function-name lookup +%define class-name HttpHeaderHashTable +%define word-array-name HttpHeaderDefinitionsTable +%compare-lengths +%compare-strncmp +%readonly-tables +%enum +%global-table +%ignore-case +%struct-type +struct HeaderTableRecord; +%% +Accept, Http::HdrType::ACCEPT, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader +Accept-Charset, Http::HdrType::ACCEPT_CHARSET, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader +Accept-Encoding, Http::HdrType::ACCEPT_ENCODING, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader|HdrKind::ReplyHeader +Accept-Language, Http::HdrType::ACCEPT_LANGUAGE, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader +Accept-Ranges, Http::HdrType::ACCEPT_RANGES, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader +Age, Http::HdrType::AGE, Http::HdrFieldType::ftInt, HdrKind::ReplyHeader +Allow, Http::HdrType::ALLOW, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::EntityHeader|HdrKind::Denied304Header +Alternate-Protocol, Http::HdrType::ALTERNATE_PROTOCOL, Http::HdrFieldType::ftStr, HdrKind::HopByHopHeader +Authentication-Info, Http::HdrType::AUTHENTICATION_INFO, Http::HdrFieldType::ftStr, HdrKind::ListHeader +Authorization, Http::HdrType::AUTHORIZATION, Http::HdrFieldType::ftStr, HdrKind::RequestHeader +Cache-Control, Http::HdrType::CACHE_CONTROL, Http::HdrFieldType::ftPCc, HdrKind::ListHeader|HdrKind::GeneralHeader +Connection, Http::HdrType::CONNECTION, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader|HdrKind::HopByHopHeader|HdrKind::Denied304Header +Content-Base, Http::HdrType::CONTENT_BASE, Http::HdrFieldType::ftStr, HdrKind::EntityHeader +Content-Disposition, Http::HdrType::CONTENT_DISPOSITION, Http::HdrFieldType::ftStr, HdrKind::None +Content-Encoding, Http::HdrType::CONTENT_ENCODING, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::EntityHeader|HdrKind::Denied304Header +Content-Language, Http::HdrType::CONTENT_LANGUAGE, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::EntityHeader|HdrKind::Denied304Header +Content-Length, Http::HdrType::CONTENT_LENGTH, Http::HdrFieldType::ftInt64, HdrKind::EntityHeader|HdrKind::Denied304Header +Content-Location, Http::HdrType::CONTENT_LOCATION, Http::HdrFieldType::ftStr, HdrKind::EntityHeader +Content-MD5, Http::HdrType::CONTENT_MD5, Http::HdrFieldType::ftStr, HdrKind::EntityHeader|HdrKind::Denied304Header +Content-Range, Http::HdrType::CONTENT_RANGE, Http::HdrFieldType::ftPContRange, HdrKind::EntityHeader|HdrKind::Denied304Header +Content-Type, Http::HdrType::CONTENT_TYPE, Http::HdrFieldType::ftStr, HdrKind::EntityHeader|HdrKind::Denied304Header +Cookie, Http::HdrType::COOKIE, Http::HdrFieldType::ftStr, HdrKind::None +Cookie2, Http::HdrType::COOKIE2, Http::HdrFieldType::ftStr, HdrKind::None +Date, Http::HdrType::DATE, Http::HdrFieldType::ftDate_1123, HdrKind::GeneralHeader +ETag, Http::HdrType::ETAG, Http::HdrFieldType::ftETag, HdrKind::EntityHeader +Expect, Http::HdrType::EXPECT, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader +Expires, Http::HdrType::EXPIRES, Http::HdrFieldType::ftDate_1123, HdrKind::EntityHeader +Forwarded, Http::HdrType::FORWARDED, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader +From, Http::HdrType::FROM, Http::HdrFieldType::ftStr, HdrKind::RequestHeader +Host, Http::HdrType::HOST, Http::HdrFieldType::ftStr, HdrKind::RequestHeader +HTTP2-Settings, Http::HdrType::HTTP2_SETTINGS, Http::HdrFieldType::ftStr, HdrKind::RequestHeader|HdrKind::HopByHopHeader +If-Match, Http::HdrType::IF_MATCH, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader +If-Modified-Since, Http::HdrType::IF_MODIFIED_SINCE, Http::HdrFieldType::ftDate_1123, HdrKind::RequestHeader +If-None-Match, Http::HdrType::IF_NONE_MATCH, Http::HdrFieldType::ftStr, HdrKind::ListHeader +If-Range, Http::HdrType::IF_RANGE, Http::HdrFieldType::ftDate_1123_or_ETag, HdrKind::None +If-Unmodified-Since, Http::HdrType::IF_UNMODIFIED_SINCE, Http::HdrFieldType::ftDate_1123, HdrKind::None +Keep-Alive, Http::HdrType::KEEP_ALIVE, Http::HdrFieldType::ftStr, HdrKind::HopByHopHeader|HdrKind::Denied304Header +Key, Http::HdrType::KEY, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader +Last-Modified, Http::HdrType::LAST_MODIFIED, Http::HdrFieldType::ftDate_1123, HdrKind::EntityHeader|HdrKind::Denied304Header +Link, Http::HdrType::LINK, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::EntityHeader +Location, Http::HdrType::LOCATION, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader +Max-Forwards, Http::HdrType::MAX_FORWARDS, Http::HdrFieldType::ftInt64, HdrKind::RequestHeader +Mime-Version, Http::HdrType::MIME_VERSION, Http::HdrFieldType::ftStr, HdrKind::GeneralHeader +Negotiate, Http::HdrType::NEGOTIATE, Http::HdrFieldType::ftStr, HdrKind::None +Origin, Http::HdrType::ORIGIN, Http::HdrFieldType::ftStr, HdrKind::RequestHeader +Pragma, Http::HdrType::PRAGMA, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader +Proxy-Authenticate, Http::HdrType::PROXY_AUTHENTICATE, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader|HdrKind::Denied304Header +Proxy-Authentication-Info, Http::HdrType::PROXY_AUTHENTICATION_INFO, Http::HdrFieldType::ftStr, HdrKind::ListHeader +Proxy-Authorization, Http::HdrType::PROXY_AUTHORIZATION, Http::HdrFieldType::ftStr, HdrKind::RequestHeader|HdrKind::HopByHopHeader|HdrKind::Denied304Header +Proxy-Connection, Http::HdrType::PROXY_CONNECTION, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader|HdrKind::HopByHopHeader +Proxy-support, Http::HdrType::PROXY_SUPPORT, Http::HdrFieldType::ftStr, HdrKind::ListHeader +Public, Http::HdrType::PUBLIC, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader +Range, Http::HdrType::RANGE, Http::HdrFieldType::ftPRange, HdrKind::RequestHeader +Referer, Http::HdrType::REFERER, Http::HdrFieldType::ftStr, HdrKind::RequestHeader +Request-Range, Http::HdrType::REQUEST_RANGE, Http::HdrFieldType::ftPRange, HdrKind::None +Retry-After, Http::HdrType::RETRY_AFTER, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader +Server, Http::HdrType::SERVER, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader +Set-Cookie, Http::HdrType::SET_COOKIE, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader +Set-Cookie2, Http::HdrType::SET_COOKIE2, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader +TE, Http::HdrType::TE, Http::HdrFieldType::ftStr, HdrKind::RequestHeader|HdrKind::HopByHopHeader|HdrKind::Denied304Header +Title, Http::HdrType::TITLE, Http::HdrFieldType::ftStr, HdrKind::None +Trailer, Http::HdrType::TRAILER, Http::HdrFieldType::ftStr, HdrKind::HopByHopHeader|HdrKind::Denied304Header +Transfer-Encoding, Http::HdrType::TRANSFER_ENCODING, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader|HdrKind::HopByHopHeader|HdrKind::Denied304Header +Translate, Http::HdrType::TRANSLATE, Http::HdrFieldType::ftStr, HdrKind::None +Unless-Modified-Since, Http::HdrType::UNLESS_MODIFIED_SINCE, Http::HdrFieldType::ftStr, HdrKind::None +Upgrade, Http::HdrType::UPGRADE, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader|HdrKind::HopByHopHeader|HdrKind::Denied304Header +User-Agent, Http::HdrType::USER_AGENT, Http::HdrFieldType::ftStr, HdrKind::RequestHeader +Vary, Http::HdrType::VARY, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader +Via, Http::HdrType::VIA, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader +Warning, Http::HdrType::WARNING, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader +WWW-Authenticate, Http::HdrType::WWW_AUTHENTICATE, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader +X-Cache, Http::HdrType::X_CACHE, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader +X-Cache-Lookup, Http::HdrType::X_CACHE_LOOKUP, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader +X-Forwarded-For, Http::HdrType::X_FORWARDED_FOR, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::GeneralHeader +X-Request-URI, Http::HdrType::X_REQUEST_URI, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader +X-Squid-Error, Http::HdrType::X_SQUID_ERROR, Http::HdrFieldType::ftStr, HdrKind::ReplyHeader +X-Accelerator-Vary, Http::HdrType::HDR_X_ACCELERATOR_VARY, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader +X-Next-Services, Http::HdrType::X_NEXT_SERVICES, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::ReplyHeader +Surrogate-Capability, Http::HdrType::SURROGATE_CAPABILITY, Http::HdrFieldType::ftStr, HdrKind::ListHeader|HdrKind::RequestHeader +Surrogate-Control, Http::HdrType::SURROGATE_CONTROL, Http::HdrFieldType::ftPSc, HdrKind::ListHeader|HdrKind::ReplyHeader +Front-End-Https, Http::HdrType::FRONT_END_HTTPS, Http::HdrFieldType::ftStr, HdrKind::None +FTP-Command, Http::HdrType::FTP_COMMAND, Http::HdrFieldType::ftStr, HdrKind::None +FTP-Arguments, Http::HdrType::FTP_ARGUMENTS, Http::HdrFieldType::ftStr, HdrKind::None +FTP-Pre, Http::HdrType::FTP_PRE, Http::HdrFieldType::ftStr, HdrKind::None +FTP-Status, Http::HdrType::FTP_STATUS, Http::HdrFieldType::ftInt, HdrKind::None +FTP-Reason, Http::HdrType::FTP_REASON, Http::HdrFieldType::ftStr, HdrKind::None +Other:, Http::HdrType::OTHER, Http::HdrFieldType::ftStr, HdrKind::EntityHeader +*INVALID*:, Http::HdrType::BAD_HDR, Http::HdrFieldType::ftInvalid, HdrKind::None +%% -- 2.39.5