Refine the REST examples; refine the http message parsing.

This commit is contained in:
Adam Gu
2018-04-13 17:52:40 +08:00
parent 803ae3eb5f
commit 4e35648b29
9 changed files with 264 additions and 101 deletions
+11 -21
View File
@@ -43,32 +43,22 @@ public:
SetHeader(kContentType, content_type);
}
void SetContent(std::string&& content) {
content_ = std::move(content);
SetContentLength(content_.size());
}
void SetContent(const std::string& content) {
content_ = content;
SetContentLength(content_.size());
}
private:
void SetContentLength(std::size_t content_length) {
content_length_ = content_length;
SetHeader(kContentLength, std::to_string(content_length));
}
// Use move semantics to avoid copy.
void set_content(std::string&& content) {
content_ = std::move(content);
}
void AppendContent(const char* data, std::size_t count) {
content_.append(data, count);
}
void AppendContent(const std::string& data) {
content_.append(data);
}
bool IsContentFull() const {
return IsContentLengthValid() && content_.length() >= content_length_;
}
bool IsContentLengthValid() const {
return content_length_ != kInvalidLength;
}
protected:
// Start line with trailing "\r\n".
std::string start_line_;
+29 -12
View File
@@ -9,6 +9,7 @@ namespace webcc {
HttpParser::HttpParser(HttpMessage* message)
: message_(message)
, content_length_(kInvalidLength)
, start_line_parsed_(false)
, content_length_parsed_(false)
, header_parsed_(false)
@@ -18,11 +19,11 @@ HttpParser::HttpParser(HttpMessage* message)
Error HttpParser::Parse(const char* data, std::size_t len) {
if (header_parsed_) {
// Add the data to the content.
message_->AppendContent(data, len);
AppendContent(data, len);
if (message_->IsContentFull()) {
if (IsContentFull()) {
// All content has been read.
finished_ = true;
Finish();
}
return kNoError;
@@ -66,22 +67,21 @@ Error HttpParser::Parse(const char* data, std::size_t len) {
// Headers just ended.
if (!content_length_parsed_) {
// No Content-Length, no content.
message_->SetContentLength(0);
finished_ = true;
// No Content-Length, no content. (TODO: Support chucked data)
Finish();
return kNoError;
} else {
// Invalid Content-Length in the request.
if (!message_->IsContentLengthValid()) {
if (content_length_ == kInvalidLength) {
return kHttpContentLengthError;
}
}
message_->AppendContent(pending_data_.substr(off));
AppendContent(pending_data_.substr(off));
if (message_->IsContentFull()) {
if (IsContentFull()) {
// All content has been read.
finished_ = true;
Finish();
}
} else {
// Save the unparsed piece for next parsing.
@@ -110,11 +110,28 @@ void HttpParser::ParseContentLength(const std::string& line) {
std::string value = line.substr(pos);
try {
std::size_t length = boost::lexical_cast<std::size_t>(value);
message_->SetContentLength(length);
content_length_ = boost::lexical_cast<std::size_t>(value);
} catch (boost::bad_lexical_cast&) {
}
}
}
void HttpParser::Finish() {
message_->SetContent(content_);
finished_ = true;
}
void HttpParser::AppendContent(const char* data, std::size_t count) {
content_.append(data, count);
}
void HttpParser::AppendContent(const std::string& data) {
content_.append(data);
}
bool HttpParser::IsContentFull() const {
return content_length_ != kInvalidLength &&
content_length_ <= content_.length();
}
} // namespace webcc
+14 -1
View File
@@ -13,6 +13,10 @@ class HttpParser {
public:
explicit HttpParser(HttpMessage* message);
~HttpParser() = default;
HttpParser(const HttpParser&) = delete;
HttpParser& operator=(const HttpParser&) = delete;
bool finished() const {
return finished_;
}
@@ -25,6 +29,13 @@ protected:
void ParseContentLength(const std::string& line);
void Finish();
void AppendContent(const char* data, std::size_t count);
void AppendContent(const std::string& data);
bool IsContentFull() const;
protected:
// The result HTTP message.
HttpMessage* message_;
@@ -34,7 +45,9 @@ protected:
// Data waiting to be parsed.
std::string pending_data_;
// Parsing helper flags.
// Temporary data and helper flags for parsing.
std::size_t content_length_;
std::string content_;
bool start_line_parsed_;
bool content_length_parsed_;
bool header_parsed_;
+1 -1
View File
@@ -96,7 +96,7 @@ std::vector<boost::asio::const_buffer> HttpResponse::ToBuffers() const {
buffers.push_back(boost::asio::buffer(misc_strings::CRLF));
// Content (optional)
if (IsContentLengthValid()) {
if (!content_.empty()) {
buffers.push_back(boost::asio::buffer(content_));
}
+1 -2
View File
@@ -35,8 +35,7 @@ void HttpSession::SetResponseContent(const std::string& content_type,
std::size_t content_length,
std::string&& content) {
response_.SetContentType(content_type);
response_.SetContentLength(content.length());
response_.set_content(std::move(content));
response_.SetContent(std::move(content));
}
void HttpSession::SendResponse() {
+1 -3
View File
@@ -40,11 +40,9 @@ Error SoapClient::Call(const std::string& operation,
http_request.set_method(kHttpPost);
http_request.set_url(url_);
http_request.SetContentType(kTextXmlUtf8);
http_request.SetContentLength(http_content.size());
http_request.SetContent(std::move(http_content));
http_request.SetHost(host_, port_);
http_request.SetHeader(kSoapAction, operation);
http_request.set_content(std::move(http_content));
http_request.Build();
HttpResponse http_response;