aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/http/fetch/httpparser.h
diff options
context:
space:
mode:
authorleo <leo@yandex-team.ru>2022-02-10 16:46:40 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:46:40 +0300
commit980edcd3304699edf9d4e4d6a656e585028e2a72 (patch)
tree139f47f3911484ae9af0eb347b1a88bd6c4bb35f /library/cpp/http/fetch/httpparser.h
parentb036a557f285146e5e35d4213e29a094ab907bcf (diff)
downloadydb-980edcd3304699edf9d4e4d6a656e585028e2a72.tar.gz
Restoring authorship annotation for <leo@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'library/cpp/http/fetch/httpparser.h')
-rw-r--r--library/cpp/http/fetch/httpparser.h606
1 files changed, 303 insertions, 303 deletions
diff --git a/library/cpp/http/fetch/httpparser.h b/library/cpp/http/fetch/httpparser.h
index 769828e4ae..b666707038 100644
--- a/library/cpp/http/fetch/httpparser.h
+++ b/library/cpp/http/fetch/httpparser.h
@@ -1,14 +1,14 @@
#pragma once
-
-#include "httpfsm.h"
-#include "httpheader.h"
-
+
+#include "httpfsm.h"
+#include "httpheader.h"
+
#include <library/cpp/mime/types/mime.h>
#include <util/system/yassert.h>
#include <library/cpp/http/misc/httpcodes.h>
template <size_t headermax = 100 << 10, size_t bodymax = 1 << 20>
-struct TFakeCheck {
+struct TFakeCheck {
bool Check(THttpHeader* /*header*/) {
return false;
}
@@ -22,351 +22,351 @@ struct TFakeCheck {
size_t GetMaxBodySize(THttpHeader*) {
return bodymax;
}
-};
-
-class THttpParserBase {
-public:
- enum States {
- hp_error,
- hp_eof,
- hp_in_header,
- hp_read_alive,
- hp_read_closed,
- hp_begin_chunk_header,
- hp_chunk_header,
- hp_read_chunk
- };
-
+};
+
+class THttpParserBase {
+public:
+ enum States {
+ hp_error,
+ hp_eof,
+ hp_in_header,
+ hp_read_alive,
+ hp_read_closed,
+ hp_begin_chunk_header,
+ hp_chunk_header,
+ hp_read_chunk
+ };
+
States GetState() {
return State;
}
-
+
void setAssumeConnectionClosed(int value) {
- AssumeConnectionClosed = value;
- }
-
+ AssumeConnectionClosed = value;
+ }
+
THttpHeader* GetHttpHeader() const {
return Header;
}
-
-protected:
- int CheckHeaders() {
+
+protected:
+ int CheckHeaders() {
if (Header->http_status < HTTP_OK || Header->http_status == HTTP_NO_CONTENT || Header->http_status == HTTP_NOT_MODIFIED) {
- Header->content_length = 0;
- Header->transfer_chunked = 0;
- }
- if (Header->transfer_chunked < -1) {
- Header->error = HTTP_BAD_ENCODING;
- return 1;
- } else if (Header->transfer_chunked == -1) {
- Header->transfer_chunked = 0;
- }
- if (!Header->transfer_chunked && Header->content_length < -1) {
- Header->error = HTTP_BAD_CONTENT_LENGTH;
- return 1;
- }
+ Header->content_length = 0;
+ Header->transfer_chunked = 0;
+ }
+ if (Header->transfer_chunked < -1) {
+ Header->error = HTTP_BAD_ENCODING;
+ return 1;
+ } else if (Header->transfer_chunked == -1) {
+ Header->transfer_chunked = 0;
+ }
+ if (!Header->transfer_chunked && Header->content_length < -1) {
+ Header->error = HTTP_BAD_CONTENT_LENGTH;
+ return 1;
+ }
if (Header->http_status == HTTP_OK) {
- if (Header->compression_method != HTTP_COMPRESSION_UNSET &&
- Header->compression_method != HTTP_COMPRESSION_IDENTITY &&
- Header->compression_method != HTTP_COMPRESSION_GZIP &&
+ if (Header->compression_method != HTTP_COMPRESSION_UNSET &&
+ Header->compression_method != HTTP_COMPRESSION_IDENTITY &&
+ Header->compression_method != HTTP_COMPRESSION_GZIP &&
Header->compression_method != HTTP_COMPRESSION_DEFLATE)
{
- Header->error = HTTP_BAD_CONTENT_ENCODING;
- return 1;
- }
- }
- if (Header->connection_closed == -1)
- Header->connection_closed = (Header->http_minor == 0 ||
- AssumeConnectionClosed);
+ Header->error = HTTP_BAD_CONTENT_ENCODING;
+ return 1;
+ }
+ }
+ if (Header->connection_closed == -1)
+ Header->connection_closed = (Header->http_minor == 0 ||
+ AssumeConnectionClosed);
if (!Header->transfer_chunked && !Header->connection_closed && Header->content_length < 0 && !HeadRequest) {
- Header->error = HTTP_LENGTH_UNKNOWN;
- return 1;
- }
- if (Header->http_time < 0)
- Header->http_time = 0;
- if (Header->mime_type < 0)
- Header->mime_type = MIME_UNKNOWN;
- return 0;
- }
-
- THttpHeaderParser HeaderParser;
- THttpChunkParser ChunkParser;
- States State;
- long ChunkSize;
+ Header->error = HTTP_LENGTH_UNKNOWN;
+ return 1;
+ }
+ if (Header->http_time < 0)
+ Header->http_time = 0;
+ if (Header->mime_type < 0)
+ Header->mime_type = MIME_UNKNOWN;
+ return 0;
+ }
+
+ THttpHeaderParser HeaderParser;
+ THttpChunkParser ChunkParser;
+ States State;
+ long ChunkSize;
THttpHeader* Header;
- int AssumeConnectionClosed;
- bool HeadRequest;
-};
-
+ int AssumeConnectionClosed;
+ bool HeadRequest;
+};
+
template <int isReader, typename TCheck = TFakeCheck<>>
-class THttpParserGeneric: public THttpParserBase, public TCheck {
-protected:
+class THttpParserGeneric: public THttpParserBase, public TCheck {
+protected:
long ParseGeneric(void*& buf, long& size) {
- if (!size) {
- switch (State) {
- case hp_error:
- case hp_eof:
- break;
- case hp_read_closed:
- State = hp_eof;
- break;
- case hp_in_header:
- Header->error = HTTP_HEADER_EOF;
- State = hp_error;
- break;
- case hp_read_alive:
- case hp_read_chunk:
- if (HeadRequest)
- State = hp_eof;
- else {
- Header->error = HTTP_MESSAGE_EOF;
- State = hp_error;
- }
- break;
- case hp_begin_chunk_header:
- case hp_chunk_header:
- if (HeadRequest)
- State = hp_eof;
- else {
- Header->error = HTTP_CHUNK_EOF;
- State = hp_error;
- }
- break;
- }
- return 0;
- }
- while (size) {
- int ret;
-
- switch (State) {
- case hp_error:
- return 0;
-
- case hp_eof:
- return 0;
-
- case hp_in_header:
- if ((ret = HeaderParser.Execute(buf, size)) < 0) {
- Header->error = HTTP_BAD_HEADER_STRING;
- State = hp_error;
- return 0;
- } else if (ret == 2) {
- Header->header_size += i32(HeaderParser.lastchar - (char*)buf + 1);
- size -= long(HeaderParser.lastchar - (char*)buf + 1);
- buf = HeaderParser.lastchar + 1;
- State = CheckHeaders() ? hp_error
+ if (!size) {
+ switch (State) {
+ case hp_error:
+ case hp_eof:
+ break;
+ case hp_read_closed:
+ State = hp_eof;
+ break;
+ case hp_in_header:
+ Header->error = HTTP_HEADER_EOF;
+ State = hp_error;
+ break;
+ case hp_read_alive:
+ case hp_read_chunk:
+ if (HeadRequest)
+ State = hp_eof;
+ else {
+ Header->error = HTTP_MESSAGE_EOF;
+ State = hp_error;
+ }
+ break;
+ case hp_begin_chunk_header:
+ case hp_chunk_header:
+ if (HeadRequest)
+ State = hp_eof;
+ else {
+ Header->error = HTTP_CHUNK_EOF;
+ State = hp_error;
+ }
+ break;
+ }
+ return 0;
+ }
+ while (size) {
+ int ret;
+
+ switch (State) {
+ case hp_error:
+ return 0;
+
+ case hp_eof:
+ return 0;
+
+ case hp_in_header:
+ if ((ret = HeaderParser.Execute(buf, size)) < 0) {
+ Header->error = HTTP_BAD_HEADER_STRING;
+ State = hp_error;
+ return 0;
+ } else if (ret == 2) {
+ Header->header_size += i32(HeaderParser.lastchar - (char*)buf + 1);
+ size -= long(HeaderParser.lastchar - (char*)buf + 1);
+ buf = HeaderParser.lastchar + 1;
+ State = CheckHeaders() ? hp_error
: Header->transfer_chunked ? hp_begin_chunk_header
: Header->content_length == 0 ? hp_eof
: Header->content_length > 0 ? hp_read_alive
: hp_read_closed;
- if (State == hp_begin_chunk_header) {
- // unget \n for chunk reader
+ if (State == hp_begin_chunk_header) {
+ // unget \n for chunk reader
buf = (char*)buf - 1;
- size++;
- }
- if (isReader)
- return size;
- } else {
- Header->header_size += size;
- size = 0;
- }
- break;
-
- case hp_read_alive:
- Header->entity_size += size;
+ size++;
+ }
+ if (isReader)
+ return size;
+ } else {
+ Header->header_size += size;
+ size = 0;
+ }
+ break;
+
+ case hp_read_alive:
+ Header->entity_size += size;
if (Header->entity_size >= Header->content_length) {
- State = hp_eof;
- }
+ State = hp_eof;
+ }
- TCheck::CheckDocPart(buf, size, Header);
- if (isReader)
- return size;
- size = 0;
- break;
-
- case hp_read_closed:
- Header->entity_size += size;
- TCheck::CheckDocPart(buf, size, Header);
- if (isReader)
- return size;
- size = 0;
- break;
-
- case hp_begin_chunk_header:
- ChunkParser.Init();
- State = hp_chunk_header;
+ TCheck::CheckDocPart(buf, size, Header);
+ if (isReader)
+ return size;
+ size = 0;
+ break;
+
+ case hp_read_closed:
+ Header->entity_size += size;
+ TCheck::CheckDocPart(buf, size, Header);
+ if (isReader)
+ return size;
+ size = 0;
+ break;
+
+ case hp_begin_chunk_header:
+ ChunkParser.Init();
+ State = hp_chunk_header;
[[fallthrough]];
-
- case hp_chunk_header:
- if ((ret = ChunkParser.Execute(buf, size)) < 0) {
- Header->error = i16(ret == -2 ? HTTP_CHUNK_TOO_LARGE : HTTP_BAD_CHUNK);
- State = hp_error;
- return 0;
- } else if (ret == 2) {
- Header->entity_size += i32(ChunkParser.lastchar - (char*)buf + 1);
- size -= long(ChunkParser.lastchar - (char*)buf + 1);
- buf = ChunkParser.lastchar + 1;
- ChunkSize = ChunkParser.chunk_length;
+
+ case hp_chunk_header:
+ if ((ret = ChunkParser.Execute(buf, size)) < 0) {
+ Header->error = i16(ret == -2 ? HTTP_CHUNK_TOO_LARGE : HTTP_BAD_CHUNK);
+ State = hp_error;
+ return 0;
+ } else if (ret == 2) {
+ Header->entity_size += i32(ChunkParser.lastchar - (char*)buf + 1);
+ size -= long(ChunkParser.lastchar - (char*)buf + 1);
+ buf = ChunkParser.lastchar + 1;
+ ChunkSize = ChunkParser.chunk_length;
Y_ASSERT(ChunkSize >= 0);
- State = ChunkSize ? hp_read_chunk : hp_eof;
- } else {
- Header->entity_size += size;
- size = 0;
- }
- break;
-
- case hp_read_chunk:
- if (size >= ChunkSize) {
- Header->entity_size += ChunkSize;
- State = hp_begin_chunk_header;
- TCheck::CheckDocPart(buf, ChunkSize, Header);
- if (isReader)
- return ChunkSize;
- size -= ChunkSize;
+ State = ChunkSize ? hp_read_chunk : hp_eof;
+ } else {
+ Header->entity_size += size;
+ size = 0;
+ }
+ break;
+
+ case hp_read_chunk:
+ if (size >= ChunkSize) {
+ Header->entity_size += ChunkSize;
+ State = hp_begin_chunk_header;
+ TCheck::CheckDocPart(buf, ChunkSize, Header);
+ if (isReader)
+ return ChunkSize;
+ size -= ChunkSize;
buf = (char*)buf + ChunkSize;
- } else {
- Header->entity_size += size;
- ChunkSize -= size;
- TCheck::CheckDocPart(buf, size, Header);
- if (isReader)
- return size;
- size = 0;
- }
+ } else {
+ Header->entity_size += size;
+ ChunkSize -= size;
+ TCheck::CheckDocPart(buf, size, Header);
+ if (isReader)
+ return size;
+ size = 0;
+ }
break;
- }
- }
- return size;
- }
-};
-
+ }
+ }
+ return size;
+ }
+};
+
template <class TCheck = TFakeCheck<>>
-class THttpParser: public THttpParserGeneric<0, TCheck> {
- typedef THttpParserGeneric<0, TCheck> TBaseT; //sorry avoiding gcc 3.4.6 BUG!
-public:
+class THttpParser: public THttpParserGeneric<0, TCheck> {
+ typedef THttpParserGeneric<0, TCheck> TBaseT; //sorry avoiding gcc 3.4.6 BUG!
+public:
void Init(THttpHeader* H, bool head_request = false) {
- TBaseT::Header = H;
- TBaseT::HeaderParser.Init(TBaseT::Header);
- TBaseT::State = TBaseT::hp_in_header;
- TBaseT::AssumeConnectionClosed = 0;
- TBaseT::HeadRequest = head_request;
- }
-
+ TBaseT::Header = H;
+ TBaseT::HeaderParser.Init(TBaseT::Header);
+ TBaseT::State = TBaseT::hp_in_header;
+ TBaseT::AssumeConnectionClosed = 0;
+ TBaseT::HeadRequest = head_request;
+ }
+
void Parse(void* buf, long size) {
TBaseT::ParseGeneric(buf, size);
- }
-};
-
-class TMemoReader {
-public:
+ }
+};
+
+class TMemoReader {
+public:
int Init(void* buf, long bufsize) {
- Buf = buf;
- Bufsize = bufsize;
- return 0;
- }
+ Buf = buf;
+ Bufsize = bufsize;
+ return 0;
+ }
long Read(void*& buf) {
Y_ASSERT(Bufsize >= 0);
- if (!Bufsize) {
- Bufsize = -1;
- return 0;
- }
- buf = Buf;
- long ret = Bufsize;
- Bufsize = 0;
- return ret;
- }
-
-protected:
- long Bufsize;
+ if (!Bufsize) {
+ Bufsize = -1;
+ return 0;
+ }
+ buf = Buf;
+ long ret = Bufsize;
+ Bufsize = 0;
+ return ret;
+ }
+
+protected:
+ long Bufsize;
void* Buf;
-};
-
-template <class Reader>
-class THttpReader: public THttpParserGeneric<1>, public Reader {
- typedef THttpParserGeneric<1> TBaseT;
+};
+
+template <class Reader>
+class THttpReader: public THttpParserGeneric<1>, public Reader {
+ typedef THttpParserGeneric<1> TBaseT;
-public:
+public:
using TBaseT::AssumeConnectionClosed;
- using TBaseT::Header;
- using TBaseT::ParseGeneric;
- using TBaseT::State;
-
+ using TBaseT::Header;
+ using TBaseT::ParseGeneric;
+ using TBaseT::State;
+
int Init(THttpHeader* H, int parsHeader, int assumeConnectionClosed = 0, bool headRequest = false) {
- Header = H;
- Eoferr = 1;
- Size = 0;
+ Header = H;
+ Eoferr = 1;
+ Size = 0;
AssumeConnectionClosed = assumeConnectionClosed;
HeadRequest = headRequest;
- return parsHeader ? ParseHeader() : SkipHeader();
- }
-
+ return parsHeader ? ParseHeader() : SkipHeader();
+ }
+
long Read(void*& buf) {
- long Chunk;
- do {
- if (!Size) {
- if (Eoferr != 1)
- return Eoferr;
- else if ((Size = (long)Reader::Read(Ptr)) < 0) {
- Header->error = HTTP_CONNECTION_LOST;
- return Eoferr = -1;
- }
- }
+ long Chunk;
+ do {
+ if (!Size) {
+ if (Eoferr != 1)
+ return Eoferr;
+ else if ((Size = (long)Reader::Read(Ptr)) < 0) {
+ Header->error = HTTP_CONNECTION_LOST;
+ return Eoferr = -1;
+ }
+ }
Chunk = ParseGeneric(Ptr, Size);
- buf = Ptr;
- Ptr = (char*)Ptr + Chunk;
- Size -= Chunk;
+ buf = Ptr;
+ Ptr = (char*)Ptr + Chunk;
+ Size -= Chunk;
if (State == hp_eof) {
Size = 0;
- Eoferr = 0;
+ Eoferr = 0;
} else if (State == hp_error)
- return Eoferr = -1;
- } while (!Chunk);
- return Chunk;
- }
-
-protected:
- int ParseHeader() {
- HeaderParser.Init(Header);
- State = hp_in_header;
- while (State == hp_in_header) {
- if ((Size = (long)Reader::Read(Ptr)) < 0)
- return Eoferr = -1;
+ return Eoferr = -1;
+ } while (!Chunk);
+ return Chunk;
+ }
+
+protected:
+ int ParseHeader() {
+ HeaderParser.Init(Header);
+ State = hp_in_header;
+ while (State == hp_in_header) {
+ if ((Size = (long)Reader::Read(Ptr)) < 0)
+ return Eoferr = -1;
ParseGeneric(Ptr, Size);
- }
- if (State == hp_error)
- return Eoferr = -1;
- if (State == hp_eof)
- Eoferr = 0;
- return 0;
- }
-
- int SkipHeader() {
- long hdrsize = Header->header_size;
- while (hdrsize) {
- if ((Size = (long)Reader::Read(Ptr)) <= 0)
- return Eoferr = -1;
- if (Size >= hdrsize) {
- Size -= hdrsize;
- Ptr = (char*)Ptr + hdrsize;
- break;
- }
- hdrsize -= Size;
- }
- State = Header->transfer_chunked ? hp_begin_chunk_header
+ }
+ if (State == hp_error)
+ return Eoferr = -1;
+ if (State == hp_eof)
+ Eoferr = 0;
+ return 0;
+ }
+
+ int SkipHeader() {
+ long hdrsize = Header->header_size;
+ while (hdrsize) {
+ if ((Size = (long)Reader::Read(Ptr)) <= 0)
+ return Eoferr = -1;
+ if (Size >= hdrsize) {
+ Size -= hdrsize;
+ Ptr = (char*)Ptr + hdrsize;
+ break;
+ }
+ hdrsize -= Size;
+ }
+ State = Header->transfer_chunked ? hp_begin_chunk_header
: Header->content_length == 0 ? hp_eof
: Header->content_length > 0 ? hp_read_alive
: hp_read_closed;
- Header->entity_size = 0;
- if (State == hp_eof)
- Eoferr = 0;
- else if (State == hp_begin_chunk_header) {
- // unget \n for chunk reader
- Ptr = (char*)Ptr - 1;
- ++Size;
- }
- return 0;
- }
-
+ Header->entity_size = 0;
+ if (State == hp_eof)
+ Eoferr = 0;
+ else if (State == hp_begin_chunk_header) {
+ // unget \n for chunk reader
+ Ptr = (char*)Ptr - 1;
+ ++Size;
+ }
+ return 0;
+ }
+
void* Ptr;
- long Size;
+ long Size;
int Eoferr;
-};
+};