Throw exception from inside HttpClientSession.Request().

This commit is contained in:
Chunting Gu
2019-03-08 11:06:19 +08:00
parent 31d0ea3c9d
commit 3647407b8b
8 changed files with 89 additions and 58 deletions
+12
View File
@@ -8,6 +8,8 @@ namespace webcc {
const char* DescribeError(Error error) {
switch (error) {
case kSchemaError:
return "Schema error";
case kHostResolveError:
return "Host resolve error";
case kEndpointConnectError:
@@ -29,4 +31,14 @@ const char* DescribeError(Error error) {
}
}
Exception::Exception(Error error, bool timeout, const std::string& details)
: error_(error), timeout_(timeout), msg_(DescribeError(error)) {
if (timeout) {
msg_ += " (timeout)";
}
if (!details.empty()) {
msg_ += " (" + details + ")";
}
}
} // namespace webcc
+49 -26
View File
@@ -33,9 +33,8 @@
namespace webcc {
// -----------------------------------------------------------------------------
// Constants
const char* const CRLF = "\r\n";
const char* const kCRLF = "\r\n";
// Default buffer size for socket reading.
const std::size_t kBufferSize = 1024;
@@ -54,30 +53,7 @@ const std::size_t kMaxDumpSize = 2048;
const char* const kPort80 = "80";
const char* const kPort443 = "443";
// Client side error codes.
enum Error {
kNoError = 0, // i.e., OK
kHostResolveError,
kEndpointConnectError,
kHandshakeError, // HTTPS handshake
kSocketReadError,
kSocketWriteError,
// HTTP error.
// E.g., failed to parse HTTP response (invalid content length, etc.).
kHttpError,
// Server error.
// E.g., HTTP status 500 + SOAP Fault element.
kServerError,
// XML parsing error.
kXmlError,
};
// Return a descriptive message for the given error code.
const char* DescribeError(Error error);
// -----------------------------------------------------------------------------
// HTTP headers.
namespace http {
@@ -146,6 +122,53 @@ const char* const kUtf8 = "utf-8";
} // namespace http
// -----------------------------------------------------------------------------
// Client side error codes.
enum Error {
kNoError = 0, // i.e., OK
kSchemaError,
kHostResolveError,
kEndpointConnectError,
kHandshakeError, // HTTPS handshake
kSocketReadError,
kSocketWriteError,
// HTTP error.
// E.g., failed to parse HTTP response (invalid content length, etc.).
kHttpError,
// Server error.
// E.g., HTTP status 500 + SOAP Fault element.
kServerError,
// XML parsing error.
kXmlError,
};
// Return a descriptive message for the given error code.
const char* DescribeError(Error error);
class Exception : public std::exception {
public:
explicit Exception(Error error = kNoError, bool timeout = false,
const std::string& details = "");
const char* what() const override {
return msg_.c_str();
}
private:
Error error_;
// If the error was caused by timeout or not.
bool timeout_;
std::string msg_;
};
} // namespace webcc
#endif // WEBCC_GLOBALS_H_
+5 -9
View File
@@ -45,8 +45,6 @@ HttpResponsePtr HttpClientSession::Request(HttpRequestArgs&& args) {
request.Prepare();
// TODO:
std::shared_ptr<HttpClientBase> impl;
if (request.url().scheme() == "http") {
@@ -54,17 +52,15 @@ HttpResponsePtr HttpClientSession::Request(HttpRequestArgs&& args) {
} else if (request.url().scheme() == "https") {
impl.reset(new HttpSslClient{args.ssl_verify_});
} else {
return HttpResponsePtr{};
throw Exception(kSchemaError, false,
"unknown schema: " + request.url().scheme());
}
if (impl) {
if (!impl->Request(request, args.buffer_size_)) {
return HttpResponsePtr{};
}
return impl->response();
if (!impl->Request(request, args.buffer_size_)) {
throw Exception(impl->error(), impl->timed_out());
}
return HttpResponsePtr{};
return impl->response();
}
HttpResponsePtr HttpClientSession::Get(const std::string& url,
+1 -2
View File
@@ -34,8 +34,7 @@ public:
std::vector<std::string>&& headers = {},
HttpRequestArgs&& args = HttpRequestArgs());
HttpResponsePtr Post(const std::string& url,
std::string&& data, bool json,
HttpResponsePtr Post(const std::string& url, std::string&& data, bool json,
std::vector<std::string>&& headers = {},
HttpRequestArgs&& args = HttpRequestArgs());
+1 -1
View File
@@ -126,7 +126,7 @@ void HttpMessage::Dump(std::ostream& os, std::size_t indent,
} else {
// Split by EOL to achieve more readability.
std::vector<std::string> splitted;
boost::split(splitted, content_, boost::is_any_of(CRLF));
boost::split(splitted, content_, boost::is_any_of(kCRLF));
std::size_t size = 0;
+2 -2
View File
@@ -81,7 +81,7 @@ bool HttpParser::ParseHeaders() {
if (!start_line_parsed_) {
start_line_parsed_ = true;
message_->set_start_line(line + CRLF);
message_->set_start_line(line + kCRLF);
if (!ParseStartLine(line)) {
return false;
}
@@ -98,7 +98,7 @@ bool HttpParser::ParseHeaders() {
bool HttpParser::NextPendingLine(std::size_t off, std::string* line,
bool remove) {
std::size_t pos = pending_data_.find(CRLF, off);
std::size_t pos = pending_data_.find(kCRLF, off);
if (pos == std::string::npos) {
return false;
+1 -1
View File
@@ -20,7 +20,7 @@ bool HttpRequest::Prepare() {
start_line_ += " ";
start_line_ += target;
start_line_ += " HTTP/1.1";
start_line_ += CRLF;
start_line_ += kCRLF;
if (url_.port().empty()) {
SetHeader(http::headers::kHost, url_.host());