Throw exception from inside HttpClientSession.Request().

master
Chunting Gu 6 years ago
parent 31d0ea3c9d
commit 3647407b8b

@ -37,34 +37,35 @@ int main() {
// - constructor: HttpRequestArgs{ "GET" }
// - move constructor: auto args = ...
//auto args = HttpRequestArgs{"GET"}.
// url("http://httpbin.org/get").
// parameters({ "key1", "value1", "key2", "value2" }).
// headers({ "Accept", "application/json" }).
// buffer_size(1000);
auto args = HttpRequestArgs{"GET"}.
url("http://httpbin.org/get").
parameters({ "key1", "value1", "key2", "value2" }).
headers({ "Accept", "application/json" }).
buffer_size(1000);
//r = session.Request(std::move(args));
r = session.Request(std::move(args));
// ---------------------------------------------------------------------------
// Use pre-defined wrappers.
//r = session.Get("http://httpbin.org/get",
// { "key1", "value1", "key2", "value2" },
// { "Accept", "application/json" },
// HttpRequestArgs{}.buffer_size(1000));
r = session.Get("http://httpbin.org/get",
{ "key1", "value1", "key2", "value2" },
{ "Accept", "application/json" },
HttpRequestArgs{}.buffer_size(1000));
// ---------------------------------------------------------------------------
// HTTPS is auto-detected from the URL schema.
r = session.Post("https://httpbin.org/post", "{ 'key': 'value' }", true,
{ "Accept", "application/json" },
HttpRequestArgs{}.ssl_verify(false).buffer_size(1000));
try {
r = session.Post("httpt://httpbin.org/post", "{ 'key': 'value' }", true,
{"Accept", "application/json"},
HttpRequestArgs{}.ssl_verify(false).buffer_size(1000));
if (r) {
std::cout << r->content() << std::endl;
}
std::cout << r->status() << std::endl << r->content() << std::endl;
GetBoostOrgLicense(session);
} catch (const webcc::Exception& e) {
std::cout << "Exception: " << e.what() << std::endl;
}
return 0;
}

@ -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

@ -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_

@ -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,

@ -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());

@ -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;

@ -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;

@ -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());

Loading…
Cancel
Save