Throw exception from inside HttpClientSession.Request().
This commit is contained in:
+18
-17
@@ -37,34 +37,35 @@ int main() {
|
|||||||
// - constructor: HttpRequestArgs{ "GET" }
|
// - constructor: HttpRequestArgs{ "GET" }
|
||||||
// - move constructor: auto args = ...
|
// - move constructor: auto args = ...
|
||||||
|
|
||||||
//auto args = HttpRequestArgs{"GET"}.
|
auto args = HttpRequestArgs{"GET"}.
|
||||||
// url("http://httpbin.org/get").
|
url("http://httpbin.org/get").
|
||||||
// parameters({ "key1", "value1", "key2", "value2" }).
|
parameters({ "key1", "value1", "key2", "value2" }).
|
||||||
// headers({ "Accept", "application/json" }).
|
headers({ "Accept", "application/json" }).
|
||||||
// buffer_size(1000);
|
buffer_size(1000);
|
||||||
|
|
||||||
//r = session.Request(std::move(args));
|
r = session.Request(std::move(args));
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Use pre-defined wrappers.
|
// Use pre-defined wrappers.
|
||||||
|
|
||||||
//r = session.Get("http://httpbin.org/get",
|
r = session.Get("http://httpbin.org/get",
|
||||||
// { "key1", "value1", "key2", "value2" },
|
{ "key1", "value1", "key2", "value2" },
|
||||||
// { "Accept", "application/json" },
|
{ "Accept", "application/json" },
|
||||||
// HttpRequestArgs{}.buffer_size(1000));
|
HttpRequestArgs{}.buffer_size(1000));
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// HTTPS is auto-detected from the URL schema.
|
// HTTPS is auto-detected from the URL schema.
|
||||||
|
|
||||||
r = session.Post("https://httpbin.org/post", "{ 'key': 'value' }", true,
|
try {
|
||||||
{ "Accept", "application/json" },
|
r = session.Post("httpt://httpbin.org/post", "{ 'key': 'value' }", true,
|
||||||
HttpRequestArgs{}.ssl_verify(false).buffer_size(1000));
|
{"Accept", "application/json"},
|
||||||
|
HttpRequestArgs{}.ssl_verify(false).buffer_size(1000));
|
||||||
|
|
||||||
if (r) {
|
std::cout << r->status() << std::endl << r->content() << std::endl;
|
||||||
std::cout << r->content() << std::endl;
|
|
||||||
|
} catch (const webcc::Exception& e) {
|
||||||
|
std::cout << "Exception: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetBoostOrgLicense(session);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ namespace webcc {
|
|||||||
|
|
||||||
const char* DescribeError(Error error) {
|
const char* DescribeError(Error error) {
|
||||||
switch (error) {
|
switch (error) {
|
||||||
|
case kSchemaError:
|
||||||
|
return "Schema error";
|
||||||
case kHostResolveError:
|
case kHostResolveError:
|
||||||
return "Host resolve error";
|
return "Host resolve error";
|
||||||
case kEndpointConnectError:
|
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
|
} // namespace webcc
|
||||||
|
|||||||
+49
-26
@@ -33,9 +33,8 @@
|
|||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Constants
|
|
||||||
|
|
||||||
const char* const CRLF = "\r\n";
|
const char* const kCRLF = "\r\n";
|
||||||
|
|
||||||
// Default buffer size for socket reading.
|
// Default buffer size for socket reading.
|
||||||
const std::size_t kBufferSize = 1024;
|
const std::size_t kBufferSize = 1024;
|
||||||
@@ -54,30 +53,7 @@ const std::size_t kMaxDumpSize = 2048;
|
|||||||
const char* const kPort80 = "80";
|
const char* const kPort80 = "80";
|
||||||
const char* const kPort443 = "443";
|
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.
|
// HTTP headers.
|
||||||
namespace http {
|
namespace http {
|
||||||
@@ -146,6 +122,53 @@ const char* const kUtf8 = "utf-8";
|
|||||||
|
|
||||||
} // namespace http
|
} // 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
|
} // namespace webcc
|
||||||
|
|
||||||
#endif // WEBCC_GLOBALS_H_
|
#endif // WEBCC_GLOBALS_H_
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ HttpResponsePtr HttpClientSession::Request(HttpRequestArgs&& args) {
|
|||||||
|
|
||||||
request.Prepare();
|
request.Prepare();
|
||||||
|
|
||||||
// TODO:
|
|
||||||
|
|
||||||
std::shared_ptr<HttpClientBase> impl;
|
std::shared_ptr<HttpClientBase> impl;
|
||||||
|
|
||||||
if (request.url().scheme() == "http") {
|
if (request.url().scheme() == "http") {
|
||||||
@@ -54,17 +52,15 @@ HttpResponsePtr HttpClientSession::Request(HttpRequestArgs&& args) {
|
|||||||
} else if (request.url().scheme() == "https") {
|
} else if (request.url().scheme() == "https") {
|
||||||
impl.reset(new HttpSslClient{args.ssl_verify_});
|
impl.reset(new HttpSslClient{args.ssl_verify_});
|
||||||
} else {
|
} else {
|
||||||
return HttpResponsePtr{};
|
throw Exception(kSchemaError, false,
|
||||||
|
"unknown schema: " + request.url().scheme());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (impl) {
|
if (!impl->Request(request, args.buffer_size_)) {
|
||||||
if (!impl->Request(request, args.buffer_size_)) {
|
throw Exception(impl->error(), impl->timed_out());
|
||||||
return HttpResponsePtr{};
|
|
||||||
}
|
|
||||||
return impl->response();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return HttpResponsePtr{};
|
return impl->response();
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpResponsePtr HttpClientSession::Get(const std::string& url,
|
HttpResponsePtr HttpClientSession::Get(const std::string& url,
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ public:
|
|||||||
std::vector<std::string>&& headers = {},
|
std::vector<std::string>&& headers = {},
|
||||||
HttpRequestArgs&& args = HttpRequestArgs());
|
HttpRequestArgs&& args = HttpRequestArgs());
|
||||||
|
|
||||||
HttpResponsePtr Post(const std::string& url,
|
HttpResponsePtr Post(const std::string& url, std::string&& data, bool json,
|
||||||
std::string&& data, bool json,
|
|
||||||
std::vector<std::string>&& headers = {},
|
std::vector<std::string>&& headers = {},
|
||||||
HttpRequestArgs&& args = HttpRequestArgs());
|
HttpRequestArgs&& args = HttpRequestArgs());
|
||||||
|
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ void HttpMessage::Dump(std::ostream& os, std::size_t indent,
|
|||||||
} else {
|
} else {
|
||||||
// Split by EOL to achieve more readability.
|
// Split by EOL to achieve more readability.
|
||||||
std::vector<std::string> splitted;
|
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;
|
std::size_t size = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ bool HttpParser::ParseHeaders() {
|
|||||||
|
|
||||||
if (!start_line_parsed_) {
|
if (!start_line_parsed_) {
|
||||||
start_line_parsed_ = true;
|
start_line_parsed_ = true;
|
||||||
message_->set_start_line(line + CRLF);
|
message_->set_start_line(line + kCRLF);
|
||||||
if (!ParseStartLine(line)) {
|
if (!ParseStartLine(line)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ bool HttpParser::ParseHeaders() {
|
|||||||
|
|
||||||
bool HttpParser::NextPendingLine(std::size_t off, std::string* line,
|
bool HttpParser::NextPendingLine(std::size_t off, std::string* line,
|
||||||
bool remove) {
|
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) {
|
if (pos == std::string::npos) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ bool HttpRequest::Prepare() {
|
|||||||
start_line_ += " ";
|
start_line_ += " ";
|
||||||
start_line_ += target;
|
start_line_ += target;
|
||||||
start_line_ += " HTTP/1.1";
|
start_line_ += " HTTP/1.1";
|
||||||
start_line_ += CRLF;
|
start_line_ += kCRLF;
|
||||||
|
|
||||||
if (url_.port().empty()) {
|
if (url_.port().empty()) {
|
||||||
SetHeader(http::headers::kHost, url_.host());
|
SetHeader(http::headers::kHost, url_.host());
|
||||||
|
|||||||
Reference in New Issue
Block a user