Skip to content
Snippets Groups Projects
Unverified Commit b03a7732 authored by Sébastien Blin's avatar Sébastien Blin Committed by GitHub
Browse files

Merge pull request #436 from binarytrails/http_expect_100-continue

http: handle expect 100-continue on post
parents 63afc8c2 87f6f3df
No related branches found
No related tags found
No related merge requests found
...@@ -221,6 +221,9 @@ public: ...@@ -221,6 +221,9 @@ public:
inline const Url& get_url() const { inline const Url& get_url() const {
return resolver_->get_url(); return resolver_->get_url();
}; };
inline std::string& to_string() {
return request_;
}
void set_certificate(std::shared_ptr<dht::crypto::Certificate> certificate); void set_certificate(std::shared_ptr<dht::crypto::Certificate> certificate);
void set_logger(std::shared_ptr<dht::Logger> logger); void set_logger(std::shared_ptr<dht::Logger> logger);
......
...@@ -43,8 +43,10 @@ Url::Url(const std::string& url): url(url) ...@@ -43,8 +43,10 @@ Url::Url(const std::string& url): url(url)
const size_t proto_end = url.find("://"); const size_t proto_end = url.find("://");
if (proto_end != std::string::npos){ if (proto_end != std::string::npos){
addr_begin = proto_end + 3; addr_begin = proto_end + 3;
if (url.substr(0, proto_end) == "https") if (url.substr(0, proto_end) == "https"){
protocol = "https"; protocol = "https";
service = protocol;
}
} }
// host and service // host and service
size_t addr_size = url.substr(addr_begin).find("/"); size_t addr_size = url.substr(addr_begin).find("/");
...@@ -173,7 +175,8 @@ Connection::set_endpoint(const asio::ip::tcp::endpoint& endpoint, const asio::ss ...@@ -173,7 +175,8 @@ Connection::set_endpoint(const asio::ip::tcp::endpoint& endpoint, const asio::ss
auto verifier = asio::ssl::rfc2818_verification(hostname); auto verifier = asio::ssl::rfc2818_verification(hostname);
bool verified = verifier(preverified, ctx); bool verified = verifier(preverified, ctx);
auto verify_ec = X509_STORE_CTX_get_error(ctx.native_handle()); auto verify_ec = X509_STORE_CTX_get_error(ctx.native_handle());
if (verify_ec == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN /*19*/) if (verify_ec == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT /*18*/
|| verify_ec == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN /*19*/)
verified = true; verified = true;
return verified; return verified;
} }
...@@ -231,10 +234,13 @@ Connection::async_handshake(HandlerCb cb) ...@@ -231,10 +234,13 @@ Connection::async_handshake(HandlerCb cb)
if (ec == asio::error::operation_aborted) if (ec == asio::error::operation_aborted)
return; return;
auto verify_ec = SSL_get_verify_result(ssl_socket_->asio_ssl_stream().native_handle()); auto verify_ec = SSL_get_verify_result(ssl_socket_->asio_ssl_stream().native_handle());
if (verify_ec == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN /*19*/ and logger_) if (logger_){
logger_->d("[http:client] [connection:%i] allow self-signed certificate in handshake", id_); if (verify_ec == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT /*18*/
else if (verify_ec != X509_V_OK and logger_) || verify_ec == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN /*19*/)
logger_->e("[http:client] [connection:%i] verify handshake error: %i", id_, verify_ec); logger_->d("[http:client] [connection:%i] allow self-signed certificate in handshake", id_);
else if (verify_ec != X509_V_OK)
logger_->e("[http:client] [connection:%i] verify handshake error: %i", id_, verify_ec);
}
if (cb) if (cb)
cb(ec); cb(ec);
}); });
...@@ -520,14 +526,18 @@ void ...@@ -520,14 +526,18 @@ void
Request::build() Request::build()
{ {
std::stringstream request; std::stringstream request;
bool append_body = true;
// first header // first header
request << header_.method().c_str() << " " << header_.request_target() << " " << request << header_.method().c_str() << " " << header_.request_target() << " " <<
"HTTP/" << header_.http_major() << "." << header_.http_minor() << "\r\n"; "HTTP/" << header_.http_major() << "." << header_.http_minor() << "\r\n";
// other headers // other headers
for (auto header: headers_) for (auto header: headers_){
request << restinio::field_to_string(header.first) << ": " << header.second << "\r\n"; request << restinio::field_to_string(header.first) << ": " << header.second << "\r\n";
if (header.first == restinio::http_field_t::expect and header.second == "100-continue")
append_body = false;
}
// last connection header // last connection header
std::string conn_str = ""; std::string conn_str = "";
...@@ -546,13 +556,11 @@ Request::build() ...@@ -546,13 +556,11 @@ Request::build()
request << "Connection: " << conn_str << "\r\n"; request << "Connection: " << conn_str << "\r\n";
// body & content-length // body & content-length
if (!body_.empty()){ if (!body_.empty())
request << "Content-Length: " << body_.size() << "\r\n\r\n"; request << "Content-Length: " << body_.size() << "\r\n\r\n";
request << body_;
}
// last delim // last delim
request << "\r\n"; if (append_body)
request << body_ << "\r\n";
request_ = request.str(); request_ = request.str();
} }
...@@ -713,6 +721,7 @@ Request::connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb) ...@@ -713,6 +721,7 @@ Request::connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb)
if (certificate_) if (certificate_)
conn_->set_endpoint(endpoint, asio::ssl::verify_peer conn_->set_endpoint(endpoint, asio::ssl::verify_peer
| asio::ssl::verify_fail_if_no_peer_cert); | asio::ssl::verify_fail_if_no_peer_cert);
if (conn_ and conn_->is_open() and conn_->is_ssl()){ if (conn_ and conn_->is_open() and conn_->is_ssl()){
conn_->async_handshake([this, cb](const asio::error_code& ec){ conn_->async_handshake([this, cb](const asio::error_code& ec){
if (ec == asio::error::operation_aborted) if (ec == asio::error::operation_aborted)
...@@ -851,9 +860,17 @@ Request::handle_response_header(const asio::error_code& ec) ...@@ -851,9 +860,17 @@ Request::handle_response_header(const asio::error_code& ec)
headers.append(header + "\n"); headers.append(header + "\n");
} }
headers.append("\n"); headers.append("\n");
// parse the headers
parse_request(headers); parse_request(headers);
if (headers_[restinio::http_field_t::expect] == "100-continue" and response_.status_code != 200){
notify_state_change(State::SENDING);
request_.append(body_);
std::ostream request_stream(&conn_->input());
request_stream << body_ << "\r\n";
conn_->async_write(std::bind(&Request::handle_request, this, std::placeholders::_1));
return;
}
// has content-length // has content-length
auto content_length_it = response_.headers.find(HTTP_HEADER_CONTENT_LENGTH); auto content_length_it = response_.headers.find(HTTP_HEADER_CONTENT_LENGTH);
if (content_length_it != response_.headers.end()) if (content_length_it != response_.headers.end())
......
...@@ -53,6 +53,20 @@ HttpTester::test_parse_url() { ...@@ -53,6 +53,20 @@ HttpTester::test_parse_url() {
CPPUNIT_ASSERT(parsed.target == "/"); CPPUNIT_ASSERT(parsed.target == "/");
} }
void
HttpTester::test_parse_https_url_no_service() {
// Arrange
std::string url = "https://jami.net/";
// Act
dht::http::Url parsed (url);
// Assert
CPPUNIT_ASSERT(parsed.url == url);
CPPUNIT_ASSERT(parsed.protocol == "https");
CPPUNIT_ASSERT(parsed.host == "jami.net");
CPPUNIT_ASSERT(parsed.service == "https");
CPPUNIT_ASSERT(parsed.target == "/");
}
void void
HttpTester::test_parse_url_no_prefix_no_target() { HttpTester::test_parse_url_no_prefix_no_target() {
// Arrange // Arrange
......
...@@ -31,6 +31,7 @@ namespace test { ...@@ -31,6 +31,7 @@ namespace test {
class HttpTester : public CppUnit::TestFixture { class HttpTester : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(HttpTester); CPPUNIT_TEST_SUITE(HttpTester);
CPPUNIT_TEST(test_parse_url); CPPUNIT_TEST(test_parse_url);
CPPUNIT_TEST(test_parse_https_url_no_service);
CPPUNIT_TEST(test_parse_url_no_prefix_no_target); CPPUNIT_TEST(test_parse_url_no_prefix_no_target);
CPPUNIT_TEST(test_parse_url_target); CPPUNIT_TEST(test_parse_url_target);
CPPUNIT_TEST(test_parse_url_query); CPPUNIT_TEST(test_parse_url_query);
...@@ -57,6 +58,7 @@ class HttpTester : public CppUnit::TestFixture { ...@@ -57,6 +58,7 @@ class HttpTester : public CppUnit::TestFixture {
* Test parse urls * Test parse urls
*/ */
void test_parse_url(); void test_parse_url();
void test_parse_https_url_no_service();
void test_parse_url_no_prefix_no_target(); void test_parse_url_no_prefix_no_target();
void test_parse_url_target(); void test_parse_url_target();
void test_parse_url_query(); void test_parse_url_query();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment