Refine parser

This commit is contained in:
Chunting Gu
2019-04-23 13:06:04 +08:00
parent 2a868c4dc1
commit 2fe4024511
7 changed files with 63 additions and 80 deletions
+25 -41
View File
@@ -139,54 +139,40 @@ bool Parser::GetNextLine(std::size_t off, std::string* line, bool erase) {
bool Parser::ParseHeaderLine(const std::string& line) {
Header header;
if (!Split2(line, ':', &header.first, &header.second)) {
LOG_ERRO("Invalid header: %s", line.c_str());
return false;
}
do {
if (!chunked_ && !content_length_parsed_) {
if (boost::iequals(header.first, headers::kContentLength)) {
content_length_parsed_ = true;
if (boost::iequals(header.first, headers::kContentLength)) {
content_length_parsed_ = true;
if (!StringToSizeT(header.second, 10, &content_length_)) {
LOG_ERRO("Invalid content length: %s.", header.second.c_str());
return false;
}
LOG_INFO("Content length: %u.", content_length_);
// Reserve memory to avoid frequent reallocation when append.
try {
content_.reserve(content_length_);
} catch (const std::exception& e) {
LOG_ERRO("Failed to reserve content memory: %s.", e.what());
return false;
}
break;
}
if (!StringToSizeT(header.second, 10, &content_length_)) {
LOG_ERRO("Invalid content length: %s.", header.second.c_str());
return false;
}
// TODO: Replace `!chunked_` with <TransferEncodingParsed>.
if (!chunked_ && !content_length_parsed_) {
if (boost::iequals(header.first, headers::kTransferEncoding)) {
if (header.second == "chunked") {
// The content is chunked.
chunked_ = true;
}
LOG_INFO("Content length: %u.", content_length_);
break;
}
// Reserve memory to avoid frequent reallocation when append.
try {
content_.reserve(content_length_);
} catch (const std::exception& e) {
LOG_ERRO("Failed to reserve content memory: %s.", e.what());
return false;
}
} while (false);
// Parse Content-Type.
if (boost::iequals(header.first, headers::kContentType)) {
} else if (boost::iequals(header.first, headers::kContentType)) {
ContentType content_type(header.second);
if (!content_type.Valid()) {
LOG_ERRO("Invalid content-type header: %s", header.second.c_str());
return false;
} else {
message_->SetContentType(content_type);
}
} else if (boost::iequals(header.first, headers::kTransferEncoding)) {
if (header.second == "chunked") {
// The content is chunked.
chunked_ = true;
}
message_->SetContentType(content_type);
}
message_->SetHeader(std::move(header));
@@ -220,7 +206,7 @@ bool Parser::ParseFixedContent(const char* data, std::size_t length) {
pending_data_.clear();
}
// NOTE: Don't have to firstly put the data to the pending data.
// Don't have to firstly put the data to the pending data.
AppendContent(data, length);
if (IsContentFull()) {
@@ -232,13 +218,8 @@ bool Parser::ParseFixedContent(const char* data, std::size_t length) {
}
bool Parser::ParseChunkedContent(const char* data, std::size_t length) {
// Append the new data to the pending data.
// NOTE: It's more difficult to avoid this than fixed-length content.
pending_data_.append(data, length);
LOG_VERB("Parse chunked content (pending data size: %u).",
pending_data_.size());
while (true) {
// Read chunk-size if necessary.
if (chunk_size_ == kInvalidLength) {
@@ -321,6 +302,9 @@ bool Parser::Finish() {
return true;
}
// Could be kInvalidLength when chunked.
message_->set_content_length(content_length_);
if (!IsContentCompressed()) {
message_->SetContent(std::move(content_), false);
return true;