Refactor and improve CTL and other code

This commit is contained in:
Justine Tunney 2024-06-04 05:41:53 -07:00
parent 1d8f37a2f0
commit 9906f299bb
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
25 changed files with 5768 additions and 5350 deletions

View file

@ -62,18 +62,23 @@ TEST(ParseHttpMessage, soLittleState) {
TEST(ParseHttpMessage, testEmpty_tooShort) {
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(0, ParseHttpMessage(req, "", 0));
EXPECT_EQ(0, ParseHttpMessage(req, "", 0, 1));
}
TEST(ParseHttpMessage, testTooShort) {
TEST(ParseHttpMessage, testShort) {
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(0, ParseHttpMessage(req, "\r\n", 2));
EXPECT_EQ(0, ParseHttpMessage(req, "HT", 2, 32768));
}
TEST(ParseHttpMessage, testBusted) {
InitHttpMessage(req, kHttpRequest);
EXPECT_SYS(EBADMSG, -1, ParseHttpMessage(req, "\r\n", 2, 2));
}
TEST(ParseHttpMessage, testNoHeaders) {
static const char m[] = "GET /foo HTTP/1.0\r\n\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("GET", method());
EXPECT_STREQ("/foo", gc(slice(m, req->uri)));
EXPECT_EQ(10, req->version);
@ -86,7 +91,7 @@ Host: foo.example\r\n\
Content-Length: 0\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("POST", method());
EXPECT_STREQ("/foo?bar%20hi", gc(slice(m, req->uri)));
EXPECT_EQ(10, req->version);
@ -98,7 +103,7 @@ Content-Length: 0\r\n\
TEST(ParseHttpMessage, testHttp101) {
static const char m[] = "GET / HTTP/1.1\r\n\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("GET", method());
EXPECT_STREQ("/", gc(slice(m, req->uri)));
EXPECT_EQ(11, req->version);
@ -107,7 +112,7 @@ TEST(ParseHttpMessage, testHttp101) {
TEST(ParseHttpMessage, testHttp100) {
static const char m[] = "GET / HTTP/1.0\r\n\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("GET", method());
EXPECT_STREQ("/", gc(slice(m, req->uri)));
EXPECT_EQ(10, req->version);
@ -116,40 +121,40 @@ TEST(ParseHttpMessage, testHttp100) {
TEST(ParseHttpMessage, testUnknownMethod_canBeUsedIfYouWant) {
static const char m[] = "#%*+_^ / HTTP/1.0\r\n\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("#%*+_^", method());
}
TEST(ParseHttpMessage, testIllegalMethod) {
static const char m[] = "ehd@oruc / HTTP/1.0\r\n\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(-1, ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(-1, ParseHttpMessage(req, m, strlen(m), strlen(m)));
}
TEST(ParseHttpMessage, testIllegalMethodCasing_weUpperCaseIt) {
static const char m[] = "get / HTTP/1.0\r\n\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("GET", method());
}
TEST(ParseHttpMessage, testEmptyMethod_isntAllowed) {
static const char m[] = " / HTTP/1.0\r\n\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(-1, ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(-1, ParseHttpMessage(req, m, strlen(m), strlen(m)));
}
TEST(ParseHttpMessage, testEmptyUri_isntAllowed) {
static const char m[] = "GET HTTP/1.0\r\n\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(-1, ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(-1, ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("GET", method());
}
TEST(ParseHttpMessage, testHttp09) {
static const char m[] = "GET /\r\n\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("GET", method());
EXPECT_STREQ("/", gc(slice(m, req->uri)));
EXPECT_EQ(9, req->version);
@ -158,7 +163,7 @@ TEST(ParseHttpMessage, testHttp09) {
TEST(ParseHttpMessage, testTinyResponse) {
static const char m[] = "HTTP/1.1 429 \r\n\r\n";
InitHttpMessage(req, kHttpResponse);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_EQ(429, req->status);
EXPECT_STREQ("", gc(slice(m, req->message)));
}
@ -170,7 +175,7 @@ GET /foo?bar%20hi HTTP/1.0\r\n\
User-Agent: hi\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("/foo?bar%20hi", gc(slice(m, req->uri)));
}
@ -181,7 +186,7 @@ User-Agent: hi\r\n\
there\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(-1, ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(-1, ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_EQ(EBADMSG, errno);
}
@ -192,7 +197,7 @@ User-Agent: hi\r\n\
: hi\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(-1, ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(-1, ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_EQ(EBADMSG, errno);
}
@ -204,7 +209,7 @@ Content-Length: 0\n\
\n\
\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m) - 1, ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m) - 1, ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("POST", method());
EXPECT_STREQ("/foo?bar%20hi", gc(slice(m, req->uri)));
EXPECT_EQ(10, req->version);
@ -226,7 +231,7 @@ Accept-Encoding: gzip, deflate\r\n\
Accept-Language: en-US,en;q=0.9\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("GET", method());
EXPECT_STREQ("/tool/net/redbean.png", gc(slice(m, req->uri)));
EXPECT_EQ(11, req->version);
@ -243,7 +248,7 @@ GET /foo?bar%20hi HTTP/1.0\r\n\
X-User-Agent: hi\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
ASSERT_EQ(1, req->xheaders.n);
EXPECT_STREQ("X-User-Agent", gc(slice(m, req->xheaders.p[0].k)));
EXPECT_STREQ("hi", gc(slice(m, req->xheaders.p[0].v)));
@ -256,7 +261,7 @@ Content-Type: text/html\r\n\
Content-Type: text/plain\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("text/plain", gc(slice(m, req->headers[kHttpContentType])));
ASSERT_EQ(0, req->xheaders.n);
}
@ -271,7 +276,7 @@ Accept: text/xml\r\n\
Accept: text/css\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("text/html", gc(slice(m, req->headers[kHttpAccept])));
ASSERT_EQ(4, req->xheaders.n);
EXPECT_STREQ("Accept", gc(slice(m, req->xheaders.p[0].k)));
@ -291,7 +296,7 @@ Accept: text/html\r\n\
Accept: text/plain\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("text/html", gc(slice(m, req->headers[kHttpAccept])));
ASSERT_EQ(1, req->xheaders.n);
EXPECT_STREQ("Accept", gc(slice(m, req->xheaders.p[0].k)));
@ -306,7 +311,7 @@ ACCEPT-ENCODING: gzip\r\n\
ACCEPT-encoding: bzip2\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_TRUE(HeaderHas(req, m, kHttpAcceptEncoding, "gzip", -1));
EXPECT_TRUE(HeaderHas(req, m, kHttpAcceptEncoding, "deflate", -1));
EXPECT_FALSE(HeaderHas(req, m, kHttpAcceptEncoding, "funzip", -1));
@ -318,7 +323,7 @@ GET / HTTP/1.1\r\n\
: boop\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(-1, ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(-1, ParseHttpMessage(req, m, strlen(m), strlen(m)));
}
TEST(HeaderHas, testHeaderOnSameLIne) {
@ -327,7 +332,7 @@ GET / HTTP/1.1\r\n\
Accept-Encoding: deflate, gzip, bzip2\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_TRUE(HeaderHas(req, m, kHttpAcceptEncoding, "gzip", -1));
EXPECT_TRUE(HeaderHas(req, m, kHttpAcceptEncoding, "deflate", -1));
EXPECT_FALSE(HeaderHas(req, m, kHttpAcceptEncoding, "funzip", -1));
@ -339,7 +344,7 @@ OPTIONS * HTTP/1.0\r\n\
User-Agent: \t hi there \t \r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_STREQ("hi there", gc(slice(m, req->headers[kHttpUserAgent])));
EXPECT_STREQ("*", gc(slice(m, req->uri)));
}
@ -349,7 +354,7 @@ TEST(ParseHttpMessage, testAbsentHost_setsSliceToZero) {
GET / HTTP/1.1\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_EQ(0, req->headers[kHttpHost].a);
EXPECT_EQ(0, req->headers[kHttpHost].b);
}
@ -360,7 +365,7 @@ GET / HTTP/1.1\r\n\
Host:\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_NE(0, req->headers[kHttpHost].a);
EXPECT_EQ(req->headers[kHttpHost].a, req->headers[kHttpHost].b);
}
@ -371,25 +376,25 @@ GET / HTTP/1.1\r\n\
Host: \r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_NE(0, req->headers[kHttpHost].a);
EXPECT_EQ(req->headers[kHttpHost].a, req->headers[kHttpHost].b);
}
TEST(ParseHttpResponse, testEmpty_tooShort) {
InitHttpMessage(req, kHttpResponse);
EXPECT_EQ(0, ParseHttpMessage(req, "", 0));
EXPECT_EQ(0, ParseHttpMessage(req, "", 0, 32768));
}
TEST(ParseHttpResponse, testTooShort) {
InitHttpMessage(req, kHttpResponse);
EXPECT_EQ(0, ParseHttpMessage(req, "\r\n", 2));
EXPECT_EQ(0, ParseHttpMessage(req, "HT", 2, 32768));
}
TEST(ParseHttpResponse, testNoHeaders) {
static const char m[] = "HTTP/1.0 200 OK\r\n\r\n";
InitHttpMessage(req, kHttpResponse);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_EQ(200, req->status);
EXPECT_STREQ("OK", gc(slice(m, req->message)));
EXPECT_EQ(10, req->version);
@ -402,7 +407,7 @@ Host: foo.example\r\n\
Content-Length: 0\r\n\
\r\n";
InitHttpMessage(req, kHttpResponse);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_EQ(200, req->status);
EXPECT_STREQ("OK", gc(slice(m, req->message)));
EXPECT_EQ(10, req->version);
@ -414,7 +419,7 @@ Content-Length: 0\r\n\
TEST(ParseHttpResponse, testHttp101) {
static const char m[] = "HTTP/1.1 300 OMG\r\n\r\n";
InitHttpMessage(req, kHttpResponse);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_EQ(300, req->status);
EXPECT_STREQ("OMG", gc(slice(m, req->message)));
EXPECT_EQ(11, req->version);
@ -423,7 +428,7 @@ TEST(ParseHttpResponse, testHttp101) {
TEST(ParseHttpResponse, testHttp100) {
static const char m[] = "HTTP/1.0 404 Not Found\r\n\r\n";
InitHttpMessage(req, kHttpResponse);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EXPECT_EQ(404, req->status);
EXPECT_STREQ("Not Found", gc(slice(m, req->message)));
EXPECT_EQ(10, req->version);
@ -433,9 +438,8 @@ void DoTiniestHttpRequest(void) {
static const char m[] = "\
GET /\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
ParseHttpMessage(req, m, sizeof(m));
DestroyHttpMessage(req);
ResetHttpMessage(req, kHttpRequest);
ParseHttpMessage(req, m, sizeof(m) - 1, sizeof(m));
}
void DoTinyHttpRequest(void) {
@ -443,9 +447,8 @@ void DoTinyHttpRequest(void) {
GET /\r\n\
Accept-Encoding: gzip\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
ParseHttpMessage(req, m, sizeof(m));
DestroyHttpMessage(req);
ResetHttpMessage(req, kHttpRequest);
ParseHttpMessage(req, m, sizeof(m) - 1, sizeof(m));
}
void DoStandardChromeRequest(void) {
@ -460,9 +463,8 @@ Referer: http://10.10.10.124:8080/\r\n\
Accept-Encoding: gzip, deflate\r\n\
Accept-Language: en-US,en;q=0.9\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
CHECK_EQ(sizeof(m) - 1, ParseHttpMessage(req, m, sizeof(m)));
DestroyHttpMessage(req);
ResetHttpMessage(req, kHttpRequest);
CHECK_EQ(sizeof(m) - 1, ParseHttpMessage(req, m, sizeof(m) - 1, sizeof(m)));
}
void DoUnstandardChromeRequest(void) {
@ -477,18 +479,16 @@ X-Referer: http://10.10.10.124:8080/\r\n\
X-Accept-Encoding: gzip, deflate\r\n\
X-Accept-Language: en-US,en;q=0.9\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
CHECK_EQ(sizeof(m) - 1, ParseHttpMessage(req, m, sizeof(m)));
DestroyHttpMessage(req);
ResetHttpMessage(req, kHttpRequest);
CHECK_EQ(sizeof(m) - 1, ParseHttpMessage(req, m, sizeof(m) - 1, sizeof(m)));
}
void DoTiniestHttpResponse(void) {
static const char m[] = "\
HTTP/1.0 200\r\n\
\r\n";
InitHttpMessage(req, kHttpResponse);
ParseHttpMessage(req, m, sizeof(m));
DestroyHttpMessage(req);
ResetHttpMessage(req, kHttpResponse);
ParseHttpMessage(req, m, sizeof(m) - 1, sizeof(m));
}
void DoTinyHttpResponse(void) {
@ -496,9 +496,8 @@ void DoTinyHttpResponse(void) {
HTTP/1.0 200\r\n\
Accept-Encoding: gzip\r\n\
\r\n";
InitHttpMessage(req, kHttpResponse);
ParseHttpMessage(req, m, sizeof(m));
DestroyHttpMessage(req);
ResetHttpMessage(req, kHttpResponse);
ParseHttpMessage(req, m, sizeof(m) - 1, sizeof(m));
}
void DoStandardHttpResponse(void) {
@ -518,9 +517,8 @@ Referrer-Policy: origin\r\n\
Strict-Transport-Security: max-age=31556900\r\n\
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://cdnjs.cloudflare.com/; frame-src 'self' https://www.google.com/recaptcha/; style-src 'self' 'unsafe-inline'\r\n\
\r\n";
InitHttpMessage(req, kHttpResponse);
CHECK_EQ(sizeof(m) - 1, ParseHttpMessage(req, m, sizeof(m)));
DestroyHttpMessage(req);
ResetHttpMessage(req, kHttpResponse);
CHECK_EQ(sizeof(m) - 1, ParseHttpMessage(req, m, sizeof(m) - 1, sizeof(m)));
}
void DoUnstandardHttpResponse(void) {
@ -545,12 +543,12 @@ x-slack-shared-secret-outcome: shared-secret\r\n\
via: envoy-www-iad-qd3r\r\n\
transfer-encoding: chunked\r\n\
\r\n";
InitHttpMessage(req, kHttpResponse);
CHECK_EQ(sizeof(m) - 1, ParseHttpMessage(req, m, sizeof(m)));
DestroyHttpMessage(req);
ResetHttpMessage(req, kHttpResponse);
CHECK_EQ(sizeof(m) - 1, ParseHttpMessage(req, m, sizeof(m) - 1, sizeof(m)));
}
BENCH(ParseHttpMessage, bench) {
InitHttpMessage(req, kHttpRequest);
EZBENCH2("DoTiniestHttpReque", donothing, DoTiniestHttpRequest());
EZBENCH2("DoTinyHttpRequest", donothing, DoTinyHttpRequest());
EZBENCH2("DoStandardChromeRe", donothing, DoStandardChromeRequest());
@ -559,6 +557,7 @@ BENCH(ParseHttpMessage, bench) {
EZBENCH2("DoTinyHttpResponse", donothing, DoTinyHttpResponse());
EZBENCH2("DoStandardHttpResp", donothing, DoStandardHttpResponse());
EZBENCH2("DoUnstandardHttpRe", donothing, DoUnstandardHttpResponse());
DestroyHttpMessage(req);
}
BENCH(HeaderHas, bench) {
@ -572,7 +571,7 @@ ACCEPT-ENCODING: gzip\r\n\
ACCEPT-encoding: bzip2\r\n\
\r\n";
InitHttpMessage(req, kHttpRequest);
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m)));
EXPECT_EQ(strlen(m), ParseHttpMessage(req, m, strlen(m), strlen(m)));
EZBENCH2("HeaderHas txt/pln", donothing,
HeaderHas(req, m, kHttpAccept, "text/plain", 7));
EZBENCH2("HeaderHas deflate", donothing,