Make HTTP message parsing a little faster

ParseHttpMessage() now does a better job avoiding malloc() calls and
headers commonly sent by CloudFlare can now be consulted in constant
time using our hard-coded perfect hash table.  This increases /claim
performance from 321k to 337k qps which is 5% faster.
This commit is contained in:
Justine Tunney 2022-10-04 06:33:10 -07:00
parent 726f04e8aa
commit 9f9b240f3d
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
5 changed files with 209 additions and 166 deletions

View file

@ -94,7 +94,13 @@ Accept-Ranges, kHttpAcceptRanges
Set-Cookie, kHttpSetCookie Set-Cookie, kHttpSetCookie
Sec-CH-UA, kHttpSecChUa Sec-CH-UA, kHttpSecChUa
Sec-CH-UA-Mobile, kHttpSecChUaMobile Sec-CH-UA-Mobile, kHttpSecChUaMobile
Sec-CH-UA-Platform, kHttpSecChUaPlatform
Sec-Fetch-Site, kHttpSecFetchSite Sec-Fetch-Site, kHttpSecFetchSite
Sec-Fetch-Mode, kHttpSecFetchMode Sec-Fetch-Mode, kHttpSecFetchMode
Sec-Fetch-User, kHttpSecFetchUser Sec-Fetch-User, kHttpSecFetchUser
Sec-Fetch-Dest, kHttpSecFetchDest Sec-Fetch-Dest, kHttpSecFetchDest
CF-RAY, kHttpCfRay
CF-Visitor, kHttpCfVisitor
CF-Connecting-IP, kHttpCfConnectingIp
CF-IPCountry, kHttpCfIpcountry
CDN-Loop, kHttpCdnLoop

View file

@ -1,7 +1,7 @@
/* ANSI-C code produced by gperf version 3.1 */ /* ANSI-C code produced by gperf version 3.1 */
/* Command-line: gperf gethttpheader.gperf */ /* Command-line: gperf gethttpheader.gperf */
/* Computed positions: -k'5,10-11,22,$' */ /* Computed positions: -k'5,10-11,22,$' */
/* clang-format off */ // clang-format off
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
@ -39,12 +39,12 @@
#line 12 "gethttpheader.gperf" #line 12 "gethttpheader.gperf"
struct thatispacked HttpHeaderSlot { char *name; char code; }; struct thatispacked HttpHeaderSlot { char *name; char code; };
#define TOTAL_KEYWORDS 87 #define TOTAL_KEYWORDS 93
#define MIN_WORD_LENGTH 2 #define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 32 #define MAX_WORD_LENGTH 32
#define MIN_HASH_VALUE 3 #define MIN_HASH_VALUE 3
#define MAX_HASH_VALUE 198 #define MAX_HASH_VALUE 181
/* maximum key range = 196, duplicates = 0 */ /* maximum key range = 179, duplicates = 0 */
#ifndef GPERF_DOWNCASE #ifndef GPERF_DOWNCASE
#define GPERF_DOWNCASE 1 #define GPERF_DOWNCASE 1
@ -98,37 +98,37 @@ __inline
inline inline
#endif #endif
#endif #endif
static unsigned int static inline unsigned int
hash (register const char *str, register size_t len) hash (register const char *str, register size_t len)
{ {
static const unsigned char asso_values[] = static const unsigned char asso_values[] =
{ {
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 55, 199, 199, 199, 199, 182, 182, 182, 182, 182, 35, 182, 182, 182, 182,
199, 199, 199, 20, 199, 199, 199, 199, 199, 199, 182, 182, 182, 5, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 15, 199, 30, 35, 10, 182, 182, 182, 182, 182, 15, 182, 30, 60, 10,
25, 15, 0, 70, 199, 55, 25, 40, 0, 45, 5, 40, 0, 40, 182, 80, 40, 90, 0, 45,
15, 20, 50, 0, 0, 5, 199, 0, 199, 20, 5, 0, 45, 0, 0, 0, 182, 0, 182, 45,
199, 199, 199, 199, 199, 199, 199, 15, 199, 30, 182, 182, 182, 182, 182, 182, 182, 15, 182, 30,
35, 10, 25, 15, 0, 70, 199, 55, 25, 40, 60, 10, 5, 40, 0, 40, 182, 80, 40, 90,
0, 45, 15, 20, 50, 0, 0, 5, 199, 0, 0, 45, 5, 0, 45, 0, 0, 0, 182, 0,
199, 20, 199, 199, 199, 199, 199, 199, 199, 199, 182, 45, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
199, 199, 199, 199, 199, 199 182, 182, 182, 182, 182, 182
}; };
register unsigned int hval = len; register unsigned int hval = len;
@ -168,7 +168,7 @@ hash (register const char *str, register size_t len)
return hval + asso_values[(unsigned char)str[len - 1]]; return hval + asso_values[(unsigned char)str[len - 1]];
} }
static const struct thatispacked HttpHeaderSlot * static inline const struct thatispacked HttpHeaderSlot *
LookupHttpHeader (register const char *str, register size_t len) LookupHttpHeader (register const char *str, register size_t len)
{ {
static const struct thatispacked HttpHeaderSlot wordlist[] = static const struct thatispacked HttpHeaderSlot wordlist[] =
@ -183,7 +183,9 @@ LookupHttpHeader (register const char *str, register size_t len)
{""}, {""}, {""}, {""},
#line 73 "gethttpheader.gperf" #line 73 "gethttpheader.gperf"
{"Location", kHttpLocation}, {"Location", kHttpLocation},
{""}, {""}, {""}, {""}, {""},
#line 17 "gethttpheader.gperf"
{"Accept", kHttpAccept},
#line 80 "gethttpheader.gperf" #line 80 "gethttpheader.gperf"
{"TE", kHttpTe}, {"TE", kHttpTe},
#line 58 "gethttpheader.gperf" #line 58 "gethttpheader.gperf"
@ -193,17 +195,13 @@ LookupHttpHeader (register const char *str, register size_t len)
{""}, {""}, {""}, {""}, {""}, {""},
#line 86 "gethttpheader.gperf" #line 86 "gethttpheader.gperf"
{"Via", kHttpVia}, {"Via", kHttpVia},
#line 45 "gethttpheader.gperf" {""},
{"ETag", kHttpEtag},
#line 16 "gethttpheader.gperf" #line 16 "gethttpheader.gperf"
{"Connection", kHttpConnection}, {"Connection", kHttpConnection},
#line 17 "gethttpheader.gperf" {""}, {""},
{"Accept", kHttpAccept},
{""},
#line 67 "gethttpheader.gperf" #line 67 "gethttpheader.gperf"
{"If-Match", kHttpIfMatch}, {"If-Match", kHttpIfMatch},
#line 39 "gethttpheader.gperf" {""},
{"Vary", kHttpVary},
#line 36 "gethttpheader.gperf" #line 36 "gethttpheader.gperf"
{"Range", kHttpRange}, {"Range", kHttpRange},
#line 92 "gethttpheader.gperf" #line 92 "gethttpheader.gperf"
@ -223,7 +221,8 @@ LookupHttpHeader (register const char *str, register size_t len)
{"If-Range", kHttpIfRange}, {"If-Range", kHttpIfRange},
#line 37 "gethttpheader.gperf" #line 37 "gethttpheader.gperf"
{"Content-Length", kHttpContentLength}, {"Content-Length", kHttpContentLength},
{""}, #line 88 "gethttpheader.gperf"
{"X-Frame-Options", kHttpXFrameOptions},
#line 66 "gethttpheader.gperf" #line 66 "gethttpheader.gperf"
{"Expect", kHttpExpect}, {"Expect", kHttpExpect},
#line 90 "gethttpheader.gperf" #line 90 "gethttpheader.gperf"
@ -234,161 +233,171 @@ LookupHttpHeader (register const char *str, register size_t len)
{""}, {""},
#line 85 "gethttpheader.gperf" #line 85 "gethttpheader.gperf"
{"WWW-Authenticate", kHttpWwwAuthenticate}, {"WWW-Authenticate", kHttpWwwAuthenticate},
#line 82 "gethttpheader.gperf" {""}, {""},
{"Transfer-Encoding", kHttpTransferEncoding}, #line 45 "gethttpheader.gperf"
#line 93 "gethttpheader.gperf" {"ETag", kHttpEtag},
{"Accept-Ranges", kHttpAcceptRanges}, #line 20 "gethttpheader.gperf"
#line 29 "gethttpheader.gperf" {"User-Agent", kHttpUserAgent},
{"From", kHttpFrom}, #line 23 "gethttpheader.gperf"
#line 88 "gethttpheader.gperf" {"Origin", kHttpOrigin},
{"X-Frame-Options", kHttpXFrameOptions},
#line 77 "gethttpheader.gperf"
{"Proxy-Connection", kHttpProxyConnection},
#line 60 "gethttpheader.gperf" #line 60 "gethttpheader.gperf"
{"Content-Base", kHttpContentBase}, {"Content-Base", kHttpContentBase},
#line 47 "gethttpheader.gperf" #line 47 "gethttpheader.gperf"
{"Content-Range", kHttpContentRange}, {"Content-Range", kHttpContentRange},
{""}, #line 39 "gethttpheader.gperf"
{"Vary", kHttpVary},
#line 24 "gethttpheader.gperf" #line 24 "gethttpheader.gperf"
{"Upgrade-Insecure-Requests", kHttpUpgradeInsecureRequests}, {"Upgrade-Insecure-Requests", kHttpUpgradeInsecureRequests},
#line 63 "gethttpheader.gperf" #line 63 "gethttpheader.gperf"
{"Content-Language", kHttpContentLanguage}, {"Content-Language", kHttpContentLanguage},
#line 28 "gethttpheader.gperf"
{"Sec-GPC", kHttpSecGpc},
{""},
#line 95 "gethttpheader.gperf"
{"Sec-CH-UA", kHttpSecChUa},
#line 18 "gethttpheader.gperf"
{"Accept-Language", kHttpAcceptLanguage},
#line 54 "gethttpheader.gperf"
{"Access-Control-Method", kHttpAccessControlMethod},
#line 42 "gethttpheader.gperf" #line 42 "gethttpheader.gperf"
{"Expires", kHttpExpires}, {"Expires", kHttpExpires},
#line 75 "gethttpheader.gperf" #line 106 "gethttpheader.gperf"
{"Proxy-Authenticate", kHttpProxyAuthenticate}, {"CDN-Loop", kHttpCdnLoop},
#line 72 "gethttpheader.gperf" #line 95 "gethttpheader.gperf"
{"Link", kHttpLink}, {"Sec-CH-UA", kHttpSecChUa},
{""},
#line 26 "gethttpheader.gperf"
{"Cookie", kHttpCookie},
#line 89 "gethttpheader.gperf"
{"X-Content-Type-Options", kHttpXContentTypeOptions},
#line 93 "gethttpheader.gperf"
{"Accept-Ranges", kHttpAcceptRanges},
#line 35 "gethttpheader.gperf"
{"Save-Data", kHttpSaveData},
#line 94 "gethttpheader.gperf" #line 94 "gethttpheader.gperf"
{"Set-Cookie", kHttpSetCookie}, {"Set-Cookie", kHttpSetCookie},
#line 25 "gethttpheader.gperf" #line 41 "gethttpheader.gperf"
{"Pragma", kHttpPragma}, {"Server", kHttpServer},
#line 49 "gethttpheader.gperf" #line 49 "gethttpheader.gperf"
{"Access-Control-Allow-Credentials", kHttpAccessControlAllowCredentials}, {"Access-Control-Allow-Credentials", kHttpAccessControlAllowCredentials},
{""}, {""},
#line 56 "gethttpheader.gperf" #line 98 "gethttpheader.gperf"
{"Access-Control-Request-Method", kHttpAccessControlRequestMethod}, {"Sec-Fetch-Site", kHttpSecFetchSite},
#line 20 "gethttpheader.gperf" #line 71 "gethttpheader.gperf"
{"User-Agent", kHttpUserAgent}, {"Keep-Alive", kHttpKeepAlive},
#line 41 "gethttpheader.gperf" #line 102 "gethttpheader.gperf"
{"Server", kHttpServer}, {"CF-RAY", kHttpCfRay},
#line 38 "gethttpheader.gperf" #line 82 "gethttpheader.gperf"
{"Content-Type", kHttpContentType}, {"Transfer-Encoding", kHttpTransferEncoding},
#line 51 "gethttpheader.gperf" {""},
{"Access-Control-Allow-Methods", kHttpAccessControlAllowMethods}, #line 62 "gethttpheader.gperf"
{""}, {""}, {"Content-Disposition", kHttpContentDisposition},
#line 43 "gethttpheader.gperf" #line 18 "gethttpheader.gperf"
{"Content-Encoding", kHttpContentEncoding}, {"Accept-Language", kHttpAcceptLanguage},
#line 77 "gethttpheader.gperf"
{"Proxy-Connection", kHttpProxyConnection},
#line 52 "gethttpheader.gperf" #line 52 "gethttpheader.gperf"
{"Access-Control-Allow-Origin", kHttpAccessControlAllowOrigin}, {"Access-Control-Allow-Origin", kHttpAccessControlAllowOrigin},
#line 68 "gethttpheader.gperf" #line 68 "gethttpheader.gperf"
{"If-None-Match", kHttpIfNoneMatch}, {"If-None-Match", kHttpIfNoneMatch},
{""}, {""}, #line 70 "gethttpheader.gperf"
#line 23 "gethttpheader.gperf" {"If-Unmodified-Since", kHttpIfUnmodifiedSince},
{"Origin", kHttpOrigin},
#line 89 "gethttpheader.gperf"
{"X-Content-Type-Options", kHttpXContentTypeOptions},
{""}, {""},
#line 35 "gethttpheader.gperf" #line 78 "gethttpheader.gperf"
{"Save-Data", kHttpSaveData}, {"Public", kHttpPublic},
{""}, #line 28 "gethttpheader.gperf"
#line 31 "gethttpheader.gperf" {"Sec-GPC", kHttpSecGpc},
{"X-Requested-With", kHttpXRequestedWith},
#line 81 "gethttpheader.gperf"
{"Trailer", kHttpTrailer},
{""},
#line 76 "gethttpheader.gperf"
{"Proxy-Authorization", kHttpProxyAuthorization},
#line 71 "gethttpheader.gperf"
{"Keep-Alive", kHttpKeepAlive},
#line 26 "gethttpheader.gperf"
{"Cookie", kHttpCookie},
{""}, {""}, {""}, {""}, {""},
#line 84 "gethttpheader.gperf"
{"Warning", kHttpWarning},
{""}, {""},
#line 48 "gethttpheader.gperf" #line 48 "gethttpheader.gperf"
{"Accept-Charset", kHttpAcceptCharset}, {"Accept-Charset", kHttpAcceptCharset},
{""}, {""},
#line 54 "gethttpheader.gperf"
{"Access-Control-Method", kHttpAccessControlMethod},
#line 38 "gethttpheader.gperf"
{"Content-Type", kHttpContentType},
#line 75 "gethttpheader.gperf"
{"Proxy-Authenticate", kHttpProxyAuthenticate},
#line 72 "gethttpheader.gperf"
{"Link", kHttpLink},
{""},
#line 31 "gethttpheader.gperf"
{"X-Requested-With", kHttpXRequestedWith},
#line 84 "gethttpheader.gperf"
{"Warning", kHttpWarning},
{""},
#line 56 "gethttpheader.gperf"
{"Access-Control-Request-Method", kHttpAccessControlRequestMethod},
{""},
#line 65 "gethttpheader.gperf" #line 65 "gethttpheader.gperf"
{"Content-MD5", kHttpContentMd5}, {"Content-MD5", kHttpContentMd5},
#line 81 "gethttpheader.gperf"
{"Trailer", kHttpTrailer},
{""}, {""},
#line 15 "gethttpheader.gperf" #line 29 "gethttpheader.gperf"
{"Cache-Control", kHttpCacheControl}, {"From", kHttpFrom},
#line 62 "gethttpheader.gperf"
{"Content-Disposition", kHttpContentDisposition},
{""}, {""},
#line 64 "gethttpheader.gperf" #line 43 "gethttpheader.gperf"
{"Content-Location", kHttpContentLocation}, {"Content-Encoding", kHttpContentEncoding},
{""}, {""},
#line 97 "gethttpheader.gperf"
{"Sec-Fetch-Site", kHttpSecFetchSite},
{""},
#line 78 "gethttpheader.gperf"
{"Public", kHttpPublic},
#line 21 "gethttpheader.gperf" #line 21 "gethttpheader.gperf"
{"Referer", kHttpReferer}, {"Referer", kHttpReferer},
{""}, {""}, {""},
#line 32 "gethttpheader.gperf"
{"X-Forwarded-Host", kHttpXForwardedHost},
{""}, {""}, {""}, {""}, {""},
#line 30 "gethttpheader.gperf"
{"If-Modified-Since", kHttpIfModifiedSince},
{""}, {""},
#line 19 "gethttpheader.gperf"
{"Accept-Encoding", kHttpAcceptEncoding},
{""},
#line 74 "gethttpheader.gperf"
{"Max-Forwards", kHttpMaxForwards},
{""},
#line 70 "gethttpheader.gperf"
{"If-Unmodified-Since", kHttpIfUnmodifiedSince},
{""}, {""},
#line 34 "gethttpheader.gperf"
{"X-CSRF-Token", kHttpXCsrfToken},
#line 59 "gethttpheader.gperf" #line 59 "gethttpheader.gperf"
{"Authorization", kHttpAuthorization}, {"Authorization", kHttpAuthorization},
#line 100 "gethttpheader.gperf" #line 100 "gethttpheader.gperf"
{"Sec-Fetch-Dest", kHttpSecFetchDest}, {"Sec-Fetch-User", kHttpSecFetchUser},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""},
#line 87 "gethttpheader.gperf" #line 64 "gethttpheader.gperf"
{"Strict-Transport-Security", kHttpStrictTransportSecurity}, {"Content-Location", kHttpContentLocation},
#line 79 "gethttpheader.gperf" {""}, {""}, {""}, {""},
{"Retry-After", kHttpRetryAfter}, #line 104 "gethttpheader.gperf"
{"CF-Connecting-IP", kHttpCfConnectingIp},
#line 105 "gethttpheader.gperf"
{"CF-IPCountry", kHttpCfIpcountry},
#line 15 "gethttpheader.gperf"
{"Cache-Control", kHttpCacheControl},
#line 76 "gethttpheader.gperf"
{"Proxy-Authorization", kHttpProxyAuthorization},
{""},
#line 25 "gethttpheader.gperf"
{"Pragma", kHttpPragma},
{""}, {""}, {""}, {""},
#line 98 "gethttpheader.gperf" #line 101 "gethttpheader.gperf"
{"Sec-Fetch-Dest", kHttpSecFetchDest},
{""}, {""}, {""},
#line 51 "gethttpheader.gperf"
{"Access-Control-Allow-Methods", kHttpAccessControlAllowMethods},
{""}, {""}, {""},
#line 74 "gethttpheader.gperf"
{"Max-Forwards", kHttpMaxForwards},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 32 "gethttpheader.gperf"
{"X-Forwarded-Host", kHttpXForwardedHost},
{""}, {""}, {""},
#line 19 "gethttpheader.gperf"
{"Accept-Encoding", kHttpAcceptEncoding},
{""}, {""}, {""}, {""},
#line 103 "gethttpheader.gperf"
{"CF-Visitor", kHttpCfVisitor},
{""},
#line 30 "gethttpheader.gperf"
{"If-Modified-Since", kHttpIfModifiedSince},
{""}, {""}, {""}, {""},
#line 34 "gethttpheader.gperf"
{"X-CSRF-Token", kHttpXCsrfToken},
{""}, {""}, {""}, {""}, {""},
#line 44 "gethttpheader.gperf"
{"Last-Modified", kHttpLastModified},
#line 99 "gethttpheader.gperf"
{"Sec-Fetch-Mode", kHttpSecFetchMode}, {"Sec-Fetch-Mode", kHttpSecFetchMode},
#line 91 "gethttpheader.gperf" #line 91 "gethttpheader.gperf"
{"Referrer-Policy", kHttpReferrerPolicy}, {"Referrer-Policy", kHttpReferrerPolicy},
#line 79 "gethttpheader.gperf"
{"Retry-After", kHttpRetryAfter},
{""}, {""}, {""}, {""}, {""}, {""},
#line 99 "gethttpheader.gperf" #line 87 "gethttpheader.gperf"
{"Sec-Fetch-User", kHttpSecFetchUser}, {"Strict-Transport-Security", kHttpStrictTransportSecurity},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 96 "gethttpheader.gperf"
{"Sec-CH-UA-Mobile", kHttpSecChUaMobile},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 33 "gethttpheader.gperf"
{"X-Forwarded-Proto", kHttpXForwardedProto},
{""}, {""},
#line 22 "gethttpheader.gperf" #line 22 "gethttpheader.gperf"
{"X-Forwarded-For", kHttpXForwardedFor}, {"X-Forwarded-For", kHttpXForwardedFor},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""},
#line 44 "gethttpheader.gperf" #line 33 "gethttpheader.gperf"
{"Last-Modified", kHttpLastModified} {"X-Forwarded-Proto", kHttpXForwardedProto},
#line 97 "gethttpheader.gperf"
{"Sec-CH-UA-Platform", kHttpSecChUaPlatform},
{""}, {""},
#line 96 "gethttpheader.gperf"
{"Sec-CH-UA-Mobile", kHttpSecChUaMobile}
}; };
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)

View file

@ -194,6 +194,18 @@ const char *GetHttpHeaderName(int h) {
return "Sec-Fetch-User"; return "Sec-Fetch-User";
case kHttpSecFetchDest: case kHttpSecFetchDest:
return "Sec-Fetch-Dest"; return "Sec-Fetch-Dest";
case kHttpCfRay:
return "CF-RAY";
case kHttpCfVisitor:
return "CF-Visitor";
case kHttpCfConnectingIp:
return "CF-Connecting-IP";
case kHttpCfIpcountry:
return "CF-IPCountry";
case kHttpCdnLoop:
return "CDN-Loop";
case kHttpSecChUaPlatform:
return "Sec-CH-UA-Platform";
default: default:
return NULL; return NULL;
} }

View file

@ -140,7 +140,13 @@
#define kHttpSecFetchMode 84 #define kHttpSecFetchMode 84
#define kHttpSecFetchUser 85 #define kHttpSecFetchUser 85
#define kHttpSecFetchDest 86 #define kHttpSecFetchDest 86
#define kHttpHeadersMax 87 #define kHttpCfRay 87
#define kHttpCfVisitor 88
#define kHttpCfConnectingIp 89
#define kHttpCfIpcountry 90
#define kHttpSecChUaPlatform 91
#define kHttpCdnLoop 92
#define kHttpHeadersMax 93
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
@ -155,7 +161,7 @@ struct HttpHeader {
}; };
struct HttpHeaders { struct HttpHeaders {
unsigned n; unsigned n, c;
struct HttpHeader *p; struct HttpHeader *p;
}; };

View file

@ -16,12 +16,12 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/mem/alg.h"
#include "libc/mem/arraylist.internal.h"
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/intrin/bits.h" #include "libc/intrin/bits.h"
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/mem/alg.h"
#include "libc/mem/arraylist.internal.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
#include "libc/str/str.h" #include "libc/str/str.h"
@ -86,7 +86,6 @@ void DestroyHttpMessage(struct HttpMessage *r) {
*/ */
int ParseHttpMessage(struct HttpMessage *r, const char *p, size_t n) { int ParseHttpMessage(struct HttpMessage *r, const char *p, size_t n) {
int c, h, i; int c, h, i;
struct HttpHeader *x;
for (n = MIN(n, LIMIT); r->i < n; ++r->i) { for (n = MIN(n, LIMIT); r->i < n; ++r->i) {
c = p[r->i] & 0xff; c = p[r->i] & 0xff;
switch (r->t) { switch (r->t) {
@ -232,15 +231,26 @@ int ParseHttpMessage(struct HttpMessage *r, const char *p, size_t n) {
(!r->headers[h].a || !kHttpRepeatable[h])) { (!r->headers[h].a || !kHttpRepeatable[h])) {
r->headers[h].a = r->a; r->headers[h].a = r->a;
r->headers[h].b = i; r->headers[h].b = i;
} else if ((x = realloc( } else {
r->xheaders.p, if (r->xheaders.n == r->xheaders.c) {
(r->xheaders.n + 1) * sizeof(*r->xheaders.p)))) { unsigned c2;
x[r->xheaders.n].k = r->k; struct HttpHeader *p1, *p2;
x[r->xheaders.n].v.a = r->a; p1 = r->xheaders.p;
x[r->xheaders.n].v.b = i; c2 = r->xheaders.c + 2;
r->xheaders.p = x; c2 = c2 >> 1;
if ((p2 = realloc(p1, c2 * sizeof(*p1)))) {
r->xheaders.p = p2;
r->xheaders.c = c2;
}
}
if (r->xheaders.n < r->xheaders.c) {
r->xheaders.p[r->xheaders.n].k = r->k;
r->xheaders.p[r->xheaders.n].v.a = r->a;
r->xheaders.p[r->xheaders.n].v.b = i;
r->xheaders.p = r->xheaders.p;
++r->xheaders.n; ++r->xheaders.n;
} }
}
r->t = c == '\r' ? kHttpStateCr : kHttpStateLf1; r->t = c == '\r' ? kHttpStateCr : kHttpStateLf1;
break; break;
} else if ((c < 0x20 && c != '\t') || (0x7F <= c && c < 0xA0)) { } else if ((c < 0x20 && c != '\t') || (0x7F <= c && c < 0xA0)) {