/* 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"
*/
// statistics counters for headers. clients must not allow Http::HdrType::BAD_HDR to be counted
-std::vector<HttpHeaderFieldStat> headerStatsTable(Http::HdrType::ENUM_END);
+std::vector<HttpHeaderFieldStat> 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
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);
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<bool>? */
- 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<Http::HdrType>()) {
+ 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);
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)) {
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)
{
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)
{
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 "<name>:[ws]<value>" lines delimited by <CRLF>.
if (!field_ptr) {
// missing <LF>
PROF_stop(HttpHeaderParse);
- return reset();
+ clean();
+ return 0;
}
field_end = field_ptr;
"header field to prevent request smuggling attacks: {" <<
getStringPrefix(header_start, hdrLen) << "}");
PROF_stop(HttpHeaderParse);
- return reset();
+ clean();
+ return 0;
}
}
}
}
} else {
PROF_stop(HttpHeaderParse);
- return reset();
+ clean();
+ return 0;
}
}
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'));
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 */
continue;
PROF_stop(HttpHeaderParse);
- return reset();
+ clean();
+ return 0;
}
// XXX: RFC 7230 Section 3.3.3 item #4 requires sending a 502 error in
if (!Config.onoff.relaxed_header_parser) {
delete e;
PROF_stop(HttpHeaderParse);
- return reset();
+ clean();
+ return 0;
}
if (!httpHeaderParseOffset(e->value.termedBuf(), &l1)) {
continue;
PROF_stop(HttpHeaderParse);
- return reset();
+ clean();
+ return 0;
}
}
if (!Config.onoff.relaxed_header_parser) {
delete e;
PROF_stop(HttpHeaderParse);
- return reset();
+ clean();
+ return 0;
}
}
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 */
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 */
}
/*
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 */
}
/*
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);
HttpHeader::compact()
{
// TODO: optimize removal, or possibly make it so that's not needed.
- std::vector<HttpHeaderEntry *>::iterator newend;
- newend = std::remove(entries.begin(), entries.end(), static_cast<HttpHeaderEntry *>(NULL));
- entries.resize(newend-entries.begin());
+ entries.erase( std::remove(entries.begin(), entries.end(), nullptr),
+ entries.end());
}
/*
{
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);
}
}
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(), ',');
}
*/
/* 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);
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();
*/
/* 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);
{
HttpHeaderEntry *e;
- if (CBIT_TEST(ListHeadersMask, id))
+ if (Http::HeaderLookupTable.lookup(id).list)
return getList(id);
if ((e = findEntry(id)))
*/
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
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;
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 */
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)));
}
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)));
}
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));
}
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)))
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)))
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());
{
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();
}
{
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();
}
{
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());
{
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))) {
id = anId;
if (id != Http::HdrType::OTHER)
- name = Http::HeaderTable[id].name;
+ name = Http::HeaderLookupTable.lookup(id).name;
else
name = aName;
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;
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))
{
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;
*/
{
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;
*/
}
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;
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 << "'");
}
}
{
const int id = static_cast<int>(val);
const bool valid_id = Http::any_valid_header(static_cast<Http::HdrType>(id));
- const char *name = valid_id ? Http::HeaderTable[id].name : "INVALID";
+ const char *name = valid_id ? Http::HeaderLookupTable.lookup(static_cast<Http::HdrType>(id)).name : "INVALID";
int visible = count > 0;
/* for entries with zero count, list only those that belong to current type of message */
"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<Http::HdrType>()) {
+ 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));
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);
}
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;
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);
/// 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
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);
}
{
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);
}
#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"
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,...)
{
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;
}
}
/* 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;
}
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;
}
HeaderManglers::~HeaderManglers()
{
- for (int i = 0; i < Http::HdrType::ENUM_END; ++i)
+ for (auto i : WholeEnum<Http::HdrType>())
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);
}
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<Http::HdrType>())
+ 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");
}
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<Http::HdrType>()) {
+ 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");
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
typedef std::map<std::string, headerMangler, NoCaseLessThan> ManglersByName;
/// one mangler for each known header
- headerMangler known[static_cast<int>(Http::HdrType::ENUM_END)];
+ headerMangler known[static_cast<int>(Http::HdrType::enumEnd_)];
/// one mangler for each custom header
ManglersByName custom;
#include "squid.h"
#include "acl/AclSizeLimit.h"
#include "acl/FilledChecklist.h"
+#include "base/EnumIterator.h"
#include "globals.h"
#include "HttpBody.h"
#include "HttpHdrCc.h"
* 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
{
assert(Http::scNone == 0); // HttpReply::parse() interface assumes that
httpHeaderMaskInit(&Denied304HeadersMask, 0);
- httpHeaderCalcMask(&Denied304HeadersMask, Denied304HeadersArr, countof(Denied304HeadersArr));
+
+ for (auto id : WholeEnum<Http::HdrType>()) {
+ if (Http::HeaderLookupTable.lookup(id).denied304)
+ CBIT_SET(Denied304HeadersMask, id);
+ }
}
HttpReply::HttpReply() : HttpMsg(hoReply), date (0), last_modified (0),
/* 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;
#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
send-announce.h \
send-announce.cc \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
SBufDetailedStats.cc \
SBufStatsAction.h \
# X.h \
# X.cc
#nodist_tests_testX_SOURCES=\
+# tests/stubs_as_needed.cc\
# $(TESTSOURCES)
#tests_testX_LDFLAGS = $(LIBADD_DL)
#tests_testX_LDADD=\
SquidString.h \
SquidTime.h \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
tests/stub_SBufDetailedStats.cc \
String.cc \
tests/stub_StatHist.cc \
stmem.cc \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
tests/stub_SBufDetailedStats.cc \
String.cc \
refresh.cc \
RemovalPolicy.cc \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
tests/stub_SBufDetailedStats.cc \
$(SNMP_SOURCE) \
tests/stub_StatHist.cc \
stmem.cc \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
tests/stub_SBufDetailedStats.cc \
StoreFileSystem.cc \
StrList.h \
StrList.cc \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
tests/stub_SBufDetailedStats.cc \
$(SNMP_SOURCE) \
refresh.h \
refresh.cc \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
tests/stub_SBufDetailedStats.cc \
$(SNMP_SOURCE) \
refresh.cc \
RemovalPolicy.cc \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
tests/stub_SBufDetailedStats.cc \
$(SNMP_SOURCE) \
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 \
refresh.cc \
RemovalPolicy.cc \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
tests/stub_SBufDetailedStats.cc \
$(SNMP_SOURCE) \
store_key_md5.h \
store_key_md5.cc \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
tests/stub_SBufDetailedStats.cc \
String.cc \
tests/stub_helper.cc \
cbdata.cc \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
tests/stub_SBufDetailedStats.cc \
String.cc \
store_swapmeta.cc \
store_swapout.cc \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
tests/stub_SBufDetailedStats.cc \
String.cc \
refresh.cc \
RemovalPolicy.cc \
$(SBUF_SOURCE) \
+ SBufAlgos.h \
+ SBufAlgos.cc \
SBufDetailedStats.h \
tests/stub_SBufDetailedStats.cc \
$(SNMP_SOURCE) \
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 = \
return false;
value = hdr->getStrOrList(hdrId);
} else {
- if (!hdr->getByNameIfPresent(hdrName.termedBuf(), value))
+ if (!hdr->getByNameIfPresent(hdrName, value))
return false;
}
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<HttpHeader*> *
#include "acl/Data.h"
#include "HttpHeader.h"
+#include "SBuf.h"
#include "SquidString.h"
class ACLHTTPHeaderData : public ACLData<HttpHeader*>
virtual ACLData<HttpHeader*> *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<char const *> * regex_rule;
};
// 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;
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)
#define SQUID_LOOKUPTABLE_H_
#include "SBuf.h"
+#include "SBufAlgos.h"
-#include <map>
+#include <unordered_map>
/**
* a record in the initializer list for a LookupTable
}
};
-template<typename EnumType, typename RecordType = LookupTableRecord<EnumType> >
+template<typename EnumType, typename RecordType = LookupTableRecord<EnumType>, typename Hasher = CaseInsensitiveSBufHash >
class LookupTable
{
public:
}
private:
- typedef std::map<const SBuf, EnumType, SBufCaseInsensitiveLess> lookupTable_t;
+ typedef std::unordered_map<const SBuf, EnumType, Hasher> lookupTable_t;
lookupTable_t lookupTable;
EnumType invalidValue;
};
}
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;
*/
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:
*/
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 */
}
format->header = xstrdup(header);
- format->header_id = Http::HeaderLookupTable.lookup(SBuf(header));
+ format->header_id = Http::HeaderLookupTable.lookup(SBuf(header)).id;
}
void
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);
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)) {
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);
ProtocolVersion.h \
RegisteredHeaders.h \
RegisteredHeaders.cc \
+ RegisteredHeadersHash.cci \
+ RegisteredHeadersHash.gperf \
RequestMethod.cc \
RequestMethod.h \
StatusCode.cc \
($(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
#include "RegisteredHeaders.h"
#include <ostream>
+#include <vector>
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<Http::HdrType, HeaderTableRecord> 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<int>(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 */
operator<< (std::ostream &s, Http::HdrType id)
{
if (Http::any_HdrType_enum_value(id))
- s << Http::HeaderTable[id].name << '[' << static_cast<int>(id) << ']';
+ s << Http::HeaderLookupTable.lookup(id).name << '[' << static_cast<int>(id) << ']';
else
s << "Invalid-Header[" << static_cast<int>(id) << ']';
return s;
/// 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 */
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 */
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 */
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; ///<header with field values defined as #(values) in HTTP/1.1
+ bool request; ///<header is a request header
+ bool reply; ///<header is a reply header
+ bool hopbyhop; ///<header is hop by hop
+ bool denied304; ///<header is not to be updated on receiving a 304 in cache revalidation (see HttpReply.cc)
};
-/// header ID->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<Http::HdrType, HeaderTableRecord> 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<int>(id)]);
+ }
+
+private:
+ void initCache();
+ std::vector<const HeaderTableRecord *> idCache;
+ static const HeaderTableRecord BadHdr; ///<used to signal "not found" from lookups
+};
+extern const HeaderLookupTable_t HeaderLookupTable;
/// match any known header type, including OTHER and BAD
inline bool
any_HdrType_enum_value (const Http::HdrType id)
{
- return (id >= 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
--- /dev/null
+/* 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 <bug-gnu-gperf@gnu.org>."
+#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"
+
--- /dev/null
+%{
+/* 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
+%%