123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 |
- #include "httpfsm.h"
- #include "library-htfetch_ut_hreflang_in.h"
- #include "library-htfetch_ut_hreflang_out.h"
- #include <util/generic/ptr.h>
- #include <library/cpp/charset/doccodes.h>
- #include <library/cpp/testing/unittest/registar.h>
- class THttpHeaderParserTestSuite: public TTestBase {
- UNIT_TEST_SUITE(THttpHeaderParserTestSuite);
- UNIT_TEST(TestRequestHeader);
- UNIT_TEST(TestSplitRequestHeader);
- UNIT_TEST(TestTrailingData);
- UNIT_TEST(TestProxyRequestHeader);
- UNIT_TEST(TestIncorrectRequestHeader);
- UNIT_TEST(TestLastModified);
- UNIT_TEST(TestLastModifiedCorrupted);
- UNIT_TEST(TestResponseHeaderOnRequest);
- UNIT_TEST(TestRequestHeaderOnResponse);
- UNIT_TEST(TestXRobotsTagUnknownTags);
- UNIT_TEST(TestXRobotsTagMyBot);
- UNIT_TEST(TestXRobotsTagOtherBot);
- UNIT_TEST(TestXRobotsTagUnavailableAfterAware);
- UNIT_TEST(TestXRobotsTagUnavailableAfterWorks);
- UNIT_TEST(TestXRobotsTagOverridePriority);
- UNIT_TEST(TestXRobotsTagDoesNotBreakCharset);
- UNIT_TEST(TestXRobotsTagAllowsMultiline);
- UNIT_TEST(TestRelCanonical);
- UNIT_TEST(TestHreflang);
- UNIT_TEST(TestHreflangOnLongInput);
- UNIT_TEST(TestMimeType);
- UNIT_TEST(TestRepeatedContentEncoding);
- UNIT_TEST_SUITE_END();
- private:
- THolder<THttpHeaderParser> httpHeaderParser;
- private:
- void TestStart();
- void TestFinish();
- public:
- void TestRequestHeader();
- void TestSplitRequestHeader();
- void TestTrailingData();
- void TestProxyRequestHeader();
- void TestIncorrectRequestHeader();
- void TestLastModified();
- void TestLastModifiedCorrupted();
- void TestResponseHeaderOnRequest();
- void TestRequestHeaderOnResponse();
- void TestXRobotsTagUnknownTags();
- void TestXRobotsTagMyBot();
- void TestXRobotsTagOtherBot();
- void TestXRobotsTagUnavailableAfterAware();
- void TestXRobotsTagUnavailableAfterWorks();
- void TestXRobotsTagOverridePriority();
- void TestXRobotsTagDoesNotBreakCharset();
- void TestXRobotsTagAllowsMultiline();
- void TestRelCanonical();
- void TestHreflang();
- void TestHreflangOnLongInput();
- void TestMimeType();
- void TestRepeatedContentEncoding();
- };
- void THttpHeaderParserTestSuite::TestStart() {
- httpHeaderParser.Reset(new THttpHeaderParser());
- }
- void THttpHeaderParserTestSuite::TestFinish() {
- httpHeaderParser.Reset();
- }
- void THttpHeaderParserTestSuite::TestRequestHeader() {
- TestStart();
- THttpRequestHeader httpRequestHeader;
- httpHeaderParser->Init(&httpRequestHeader);
- const char* request = "GET /search?q=hi HTTP/1.1\r\n"
- "Host: www.google.ru:8080\r\n\r\n";
- i32 result = httpHeaderParser->Execute(request, strlen(request));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpRequestHeader.http_method, HTTP_METHOD_GET);
- UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.host, "www.google.ru:8080"), 0);
- UNIT_ASSERT_EQUAL(httpRequestHeader.request_uri, "/search?q=hi");
- UNIT_ASSERT_EQUAL(httpRequestHeader.GetUrl(), "http://www.google.ru:8080/search?q=hi");
- UNIT_ASSERT_EQUAL(httpHeaderParser->lastchar - request + 1,
- (i32)strlen(request));
- UNIT_ASSERT_EQUAL(httpRequestHeader.x_yandex_response_timeout,
- DEFAULT_RESPONSE_TIMEOUT);
- UNIT_ASSERT_EQUAL(httpRequestHeader.x_yandex_request_priority,
- DEFAULT_REQUEST_PRIORITY);
- UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.x_yandex_sourcename, ""), 0);
- UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.x_yandex_requesttype, ""), 0);
- UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.x_yandex_fetchoptions, ""), 0);
- TestFinish();
- UNIT_ASSERT_EQUAL(httpRequestHeader.max_age, DEFAULT_MAX_AGE);
- }
- void THttpHeaderParserTestSuite::TestSplitRequestHeader() {
- TestStart();
- const char* request =
- "GET /search?q=hi HTTP/1.1\r\n"
- "Host: www.google.ru:8080 \r\n"
- "\r\n";
- const size_t rlen = strlen(request);
- for (size_t n1 = 0; n1 < rlen; n1++) {
- for (size_t n2 = n1; n2 < rlen; n2++) {
- TString s1{request, 0, n1};
- TString s2{request, n1, n2 - n1};
- TString s3{request, n2, rlen - n2};
- UNIT_ASSERT_EQUAL(s1 + s2 + s3, request);
- THttpRequestHeader httpRequestHeader;
- UNIT_ASSERT(0 == httpHeaderParser->Init(&httpRequestHeader));
- i32 result = httpHeaderParser->Execute(s1);
- UNIT_ASSERT_EQUAL(result, 1);
- result = httpHeaderParser->Execute(s2);
- UNIT_ASSERT_EQUAL(result, 1);
- result = httpHeaderParser->Execute(s3);
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpRequestHeader.http_method, HTTP_METHOD_GET);
- UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.host, "www.google.ru:8080"), 0);
- UNIT_ASSERT_EQUAL(httpRequestHeader.request_uri, "/search?q=hi");
- }
- }
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestTrailingData() {
- TestStart();
- THttpRequestHeader httpRequestHeader;
- UNIT_ASSERT(0 == httpHeaderParser->Init(&httpRequestHeader));
- const char* request =
- "GET /search?q=hi HTTP/1.1\r\n"
- "Host: www.google.ru:8080\r\n"
- "\r\n"
- "high.ru";
- i32 result = httpHeaderParser->Execute(request, strlen(request));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpRequestHeader.http_method, HTTP_METHOD_GET);
- UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.host, "www.google.ru:8080"), 0);
- UNIT_ASSERT_EQUAL(httpRequestHeader.request_uri, "/search?q=hi");
- UNIT_ASSERT_EQUAL(TString(httpHeaderParser->lastchar + 1), "high.ru");
- UNIT_ASSERT_EQUAL(httpRequestHeader.http_minor, 1);
- UNIT_ASSERT_EQUAL(httpRequestHeader.transfer_chunked, -1);
- UNIT_ASSERT_EQUAL(httpRequestHeader.content_length, -1);
- UNIT_ASSERT_EQUAL(httpRequestHeader.connection_closed, -1);
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestProxyRequestHeader() {
- TestStart();
- THttpRequestHeader httpRequestHeader;
- httpHeaderParser->Init(&httpRequestHeader);
- const char* request =
- "GET http://www.google.ru:8080/search?q=hi HTTP/1.1\r\n"
- "X-Yandex-Response-Timeout: 1000\r\n"
- "X-Yandex-Request-Priority: 2\r\n"
- "X-Yandex-Sourcename: orange\r\n"
- "X-Yandex-Requesttype: userproxy\r\n"
- "X-Yandex-FetchOptions: d;c\r\n"
- "Cache-control: max-age=100\r\n"
- "If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT\r\n"
- "User-Agent: Yandex/1.01.001 (compatible; Win16; I)\r\n"
- "From: webadmin@yandex.ru\r\n\r\n";
- i32 result = httpHeaderParser->Execute(request, strlen(request));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpRequestHeader.http_method, HTTP_METHOD_GET);
- UNIT_ASSERT_EQUAL(httpRequestHeader.x_yandex_response_timeout, 1000);
- UNIT_ASSERT_EQUAL(httpRequestHeader.x_yandex_request_priority, 2);
- UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.x_yandex_sourcename, "orange"), 0);
- UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.x_yandex_requesttype, "userproxy"), 0);
- UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.x_yandex_fetchoptions, "d;c"), 0);
- UNIT_ASSERT_EQUAL(httpRequestHeader.max_age, 100);
- UNIT_ASSERT_VALUES_EQUAL(httpRequestHeader.if_modified_since,
- TInstant::ParseIso8601Deprecated("1994-10-29 19:43:31Z").TimeT());
- UNIT_ASSERT_EQUAL(httpRequestHeader.request_uri,
- "http://www.google.ru:8080/search?q=hi");
- UNIT_ASSERT(httpRequestHeader.GetUrl() ==
- "http://www.google.ru:8080/search?q=hi");
- UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.host, ""), 0);
- UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.from, "webadmin@yandex.ru"), 0);
- UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.user_agent,
- "Yandex/1.01.001 (compatible; Win16; I)"),
- 0);
- UNIT_ASSERT_EQUAL(httpHeaderParser->lastchar - request + 1,
- (i32)strlen(request));
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestIncorrectRequestHeader() {
- TestStart();
- THttpRequestHeader httpRequestHeader;
- httpHeaderParser->Init(&httpRequestHeader);
- const char* request = "GET /search?q=hi HTP/1.1\r\n"
- "Host: www.google.ru:8080\r\n\r\n";
- i32 result = httpHeaderParser->Execute(request, strlen(request));
- UNIT_ASSERT(result != 2);
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestLastModified() {
- TestStart();
- THttpHeader h;
- UNIT_ASSERT(0 == httpHeaderParser->Init(&h));
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "Last-Modified: Thu, 13 Aug 2009 14:27:08 GMT\r\n\r\n";
- UNIT_ASSERT(2 == httpHeaderParser->Execute(headers, strlen(headers)));
- UNIT_ASSERT_VALUES_EQUAL(
- TInstant::ParseIso8601Deprecated("2009-08-13 14:27:08Z").TimeT(),
- h.http_time);
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestLastModifiedCorrupted() {
- TestStart();
- THttpHeader h;
- UNIT_ASSERT(0 == httpHeaderParser->Init(&h));
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "Last-Modified: Thu, 13 Aug 2009 14:\r\n\r\n";
- UNIT_ASSERT(2 == httpHeaderParser->Execute(headers, strlen(headers)));
- UNIT_ASSERT(h.http_time < 0); // XXX: don't understand what is the proper value
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestXRobotsTagUnknownTags() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "x-robots-tag: asdfasdf asdf asdf,,, , noindex,noodpXXX , NOFOLLOW ,noodpnofollow\r\n\r\n";
- i32 result = httpHeaderParser->Execute(headers, strlen(headers));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpHeader.x_robots_tag, 3);
- UNIT_ASSERT_EQUAL(httpHeader.x_robots_state, "00xxx");
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestXRobotsTagMyBot() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "x-robots-tag: yandex: noindex, nofollow\r\n"
- "x-robots-tag: yandexbot: noarchive, noodp\r\n\r\n";
- i32 result = httpHeaderParser->Execute(headers, strlen(headers));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpHeader.x_robots_tag, 15);
- UNIT_ASSERT_EQUAL(httpHeader.x_robots_state, "0000x");
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestXRobotsTagOtherBot() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "x-robots-tag: google: noindex, nofollow\r\n"
- "x-robots-tag: googlebot: noarchive, noodp\r\n"
- "x-robots-tag: !still(-other) bot_: foo, noyaca\r\n\r\n";
- i32 result = httpHeaderParser->Execute(headers, strlen(headers));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpHeader.x_robots_tag, 0);
- UNIT_ASSERT_EQUAL(httpHeader.x_robots_state, "xxxxx");
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestXRobotsTagUnavailableAfterAware() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- // проверяем только что unavailable_after ничего не ломает
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "x-robots-tag: unavailable_after: 01 Jan 2999 00:00 UTC, noindex, nofollow\r\n"
- "x-robots-tag: yandex: unavailable_after: 01 Jan 2999 00:00 UTC, noarchive, noodp\r\n\r\n";
- i32 result = httpHeaderParser->Execute(headers, strlen(headers));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpHeader.x_robots_tag, 15);
- UNIT_ASSERT_EQUAL(httpHeader.x_robots_state, "0000x");
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestXRobotsTagUnavailableAfterWorks() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- // пока не поддерживается
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "x-robots-tag: unavailable_after: 01 Jan 2000 00:00 UTC\r\n\r\n";
- i32 result = httpHeaderParser->Execute(headers, strlen(headers));
- UNIT_ASSERT_EQUAL(result, 2);
- //UNIT_ASSERT_EQUAL(httpHeader.x_robots_tag, 1);
- //UNIT_ASSERT_EQUAL(httpHeader.x_robots_state, "0xxxx");
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestXRobotsTagOverridePriority() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "x-robots-tag: all, none\r\n\r\n";
- i32 result = httpHeaderParser->Execute(headers, strlen(headers));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpHeader.x_robots_state, "11xxx");
- UNIT_ASSERT_EQUAL(httpHeader.x_robots_tag, 3); // NOTE legacy behavior, should be 0 as `all` overrides
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestXRobotsTagDoesNotBreakCharset() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "X-Robots-Tag: noarchive\r\n"
- "Content-Type: application/json; charset=utf-8\r\n\r\n";
- i32 result = httpHeaderParser->Execute(headers, strlen(headers));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpHeader.mime_type, static_cast<ui8>(MIME_JSON));
- UNIT_ASSERT_EQUAL(httpHeader.charset, static_cast<ui8>(CODES_UTF8));
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestXRobotsTagAllowsMultiline() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "X-Robots-Tag\r\n"
- " :\r\n"
- " unavailable_since\r\n"
- " :\r\n"
- " ,\r\n"
- " unavailable_since\r\n"
- " :\r\n"
- " 01 Jan 2000\r\n"
- " 00:00 UTC\r\n"
- " ,\r\n"
- " yandexbot\r\n"
- " :\r\n"
- " noindex\r\n"
- " ,\r\n"
- " garbage\r\n"
- " ,\r\n"
- " nofollow\r\n"
- " ,\r\n"
- " other\r\n"
- " bot\r\n"
- " :\r\n"
- " noarchive\r\n"
- " ,\r\n"
- "Content-Type: application/json; charset=utf-8\r\n\r\n";
- i32 result = httpHeaderParser->Execute(headers, strlen(headers));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpHeader.x_robots_state, "00xxx");
- UNIT_ASSERT_EQUAL(httpHeader.mime_type, static_cast<ui8>(MIME_JSON));
- UNIT_ASSERT_EQUAL(httpHeader.charset, static_cast<ui8>(CODES_UTF8));
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestHreflang() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "link: <http://www.high.ru/>; rel='alternate'; hreflang='x-default'\r\n"
- "link: <http://www.high.ru/en.html> ;rel = 'alternate' ;hreflang = en_GB \r\n"
- "link: <http://www.high.ru/ru.html>;hreflang = ru_RU.KOI8-r ;rel = 'alternate' \r\n"
- "\r\n";
- i32 result = httpHeaderParser->Execute(headers, strlen(headers));
- UNIT_ASSERT_VALUES_EQUAL(result, 2);
- // UNIT_ASSERT_VALUES_EQUAL(strcmp(httpHeader.hreflangs, "x-default http://www.high.ru/;"), 0);
- UNIT_ASSERT_VALUES_EQUAL(httpHeader.hreflangs, "x-default http://www.high.ru/\ten_GB http://www.high.ru/en.html\tru_RU.KOI8-r http://www.high.ru/ru.html");
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestHreflangOnLongInput() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- TStringBuf testInput(hreflang_ut_in);
- TStringBuf testOut(hreflang_ut_out);
- i32 result = httpHeaderParser->Execute(testInput.data(), testInput.size());
- UNIT_ASSERT_VALUES_EQUAL(result, 2);
- UNIT_ASSERT_VALUES_EQUAL(httpHeader.hreflangs, testOut);
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestRelCanonical() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "Link: <http://yandex.ru>; rel = \"canonical\"\r\n\r\n";
- i32 result = httpHeaderParser->Execute(headers, strlen(headers));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpHeader.rel_canonical, "http://yandex.ru");
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestResponseHeaderOnRequest() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- const char* request = "GET /search?q=hi HTP/1.1\r\n"
- "Host: www.google.ru:8080\r\n\r\n";
- i32 result = httpHeaderParser->Execute(request, strlen(request));
- UNIT_ASSERT_EQUAL(result, -3);
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestRequestHeaderOnResponse() {
- TestStart();
- THttpRequestHeader httpRequestHeader;
- httpHeaderParser->Init(&httpRequestHeader);
- const char* response = "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "Last-Modified: Thu, 13 Aug 2009 14:\r\n\r\n";
- i32 result = httpHeaderParser->Execute(response, strlen(response));
- UNIT_ASSERT_EQUAL(result, -3);
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestMimeType() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- const char* headers =
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: application/json; charset=utf-8\r\n\r\n";
- i32 result = httpHeaderParser->Execute(headers, strlen(headers));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpHeader.mime_type, static_cast<ui8>(MIME_JSON));
- UNIT_ASSERT_EQUAL(httpHeader.charset, static_cast<ui8>(CODES_UTF8));
- TestFinish();
- }
- void THttpHeaderParserTestSuite::TestRepeatedContentEncoding() {
- TestStart();
- THttpHeader httpHeader;
- httpHeaderParser->Init(&httpHeader);
- const char *headers =
- "HTTP/1.1 200 OK\r\n"
- "Server: nginx\r\n"
- "Date: Mon, 15 Oct 2018 10:40:44 GMT\r\n"
- "Content-Type: text/plain\r\n"
- "Transfer-Encoding: chunked\r\n"
- "Connection: keep-alive\r\n"
- "Last-Modified: Mon, 15 Oct 2018 03:48:54 GMT\r\n"
- "ETag: W/\"5bc40e26-a956d\"\r\n"
- "X-Autoru-LB: lb-03-sas.prod.vertis.yandex.net\r\n"
- "Content-Encoding: gzip\r\n"
- "Content-Encoding: gzip\r\n"
- "X-UA-Bot: 1\r\n"
- "\r\n";
- i32 result = httpHeaderParser->Execute(headers, strlen(headers));
- UNIT_ASSERT_EQUAL(result, 2);
- UNIT_ASSERT_EQUAL(httpHeader.error, 0);
- UNIT_ASSERT_EQUAL(httpHeader.compression_method, 3);
- TestFinish();
- }
- UNIT_TEST_SUITE_REGISTRATION(THttpHeaderParserTestSuite);
- Y_UNIT_TEST_SUITE(TestHttpChunkParser) {
- static THttpChunkParser initParser() {
- THttpChunkParser parser;
- parser.Init();
- return parser;
- }
- static THttpChunkParser parseByteByByte(const TStringBuf& blob, const TVector<int>& states) {
- UNIT_ASSERT(states.size() <= blob.size());
- THttpChunkParser parser{initParser()};
- for (size_t n = 0; n < states.size(); n++) {
- const TStringBuf d{blob, n, 1};
- int code = parser.Execute(d.data(), d.size());
- Cout << TString(d).Quote() << " " << code << Endl;
- UNIT_ASSERT_EQUAL(code, states[n]);
- }
- return parser;
- }
- static THttpChunkParser parseBytesWithLastState(const TStringBuf& blob, const int last_state) {
- TVector<int> states(blob.size() - 1, 1);
- states.push_back(last_state);
- return parseByteByByte(blob, states);
- }
- Y_UNIT_TEST(TestWithoutEolHead) {
- const TStringBuf blob{
- "4\r\n"
- "____\r\n"};
- TVector<int> states{
- -1, /* 1, -1,
- 1, -1, 1, -1, 1, -1 */};
- // as soon as error happens parser state should be considered
- // undefined, state is meaningless after the very first `-1`
- // moreover, testenv produces `states[1] == -1` for this input and
- // my local build produces `states[1] == 1`.
- parseByteByByte(blob, states);
- }
- Y_UNIT_TEST(TestTrivialChunk) {
- const TStringBuf blob{
- "\r\n"
- "4\r\n"};
- THttpChunkParser parser(parseBytesWithLastState(blob, 2));
- UNIT_ASSERT_EQUAL(parser.chunk_length, 4);
- UNIT_ASSERT_EQUAL(parser.cnt64, 4);
- }
- Y_UNIT_TEST(TestNegative) {
- const TStringBuf blob{
- "\r\n"
- "-1"};
- TVector<int> states{
- 1, 1,
- -1,
- /* 1 */};
- parseByteByByte(blob, states);
- }
- Y_UNIT_TEST(TestLeadingZero) {
- const TStringBuf blob{
- "\r\n"
- "042\r\n"};
- THttpChunkParser parser(parseBytesWithLastState(blob, 2));
- UNIT_ASSERT_EQUAL(parser.chunk_length, 0x42);
- }
- Y_UNIT_TEST(TestIntOverflow) {
- const TStringBuf blob{
- "\r\n"
- "deadbeef"};
- THttpChunkParser parser(parseBytesWithLastState(blob, -2));
- UNIT_ASSERT_EQUAL(parser.chunk_length, 0);
- UNIT_ASSERT_EQUAL(parser.cnt64, 0xdeadbeef);
- }
- Y_UNIT_TEST(TestTrivialChunkWithTail) {
- const TStringBuf blob{
- "\r\n"
- "4\r\n"
- "_" // first byte of the chunk
- };
- TVector<int> states{
- 1, 1,
- 1, 1, 2,
- -1};
- parseByteByByte(blob, states);
- }
- Y_UNIT_TEST(TestLastChunk) {
- // NB: current parser does not permit whitespace before `foo`,
- // but I've never seen the feature in real-life traffic
- const TStringBuf blob{
- "\r\n"
- "000 ;foo = bar \r\n"
- "Trailer: bar\r\n"
- "\r\n"};
- THttpChunkParser parser(parseBytesWithLastState(blob, 2));
- UNIT_ASSERT_EQUAL(parser.chunk_length, 0);
- }
- }
|