Refine the REST examples; refine the http message parsing.
This commit is contained in:
+11
-21
@@ -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
@@ -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
@@ -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_;
|
||||
|
||||
@@ -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_));
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user