@@ -950,6 +950,7 @@ enum class Error {
950950 UnsupportedMultipartBoundaryChars,
951951 Compression,
952952 ConnectionTimeout,
953+ ProxyConnection,
953954
954955 // For internal use only
955956 SSLPeerCouldBeClosed_,
@@ -1888,6 +1889,7 @@ inline std::string to_string(const Error error) {
18881889 return " Unsupported HTTP multipart boundary characters" ;
18891890 case Error::Compression: return " Compression failed" ;
18901891 case Error::ConnectionTimeout: return " Connection timed out" ;
1892+ case Error::ProxyConnection: return " Proxy connection failed" ;
18911893 case Error::Unknown: return " Unknown" ;
18921894 default : break ;
18931895 }
@@ -6748,6 +6750,21 @@ inline bool ClientImpl::handle_request(Stream &strm, Request &req,
67486750
67496751 if (!ret) { return false ; }
67506752
6753+ if (res.get_header_value (" Connection" ) == " close" ||
6754+ (res.version == " HTTP/1.0" && res.reason != " Connection established" )) {
6755+ // TODO this requires a not-entirely-obvious chain of calls to be correct
6756+ // for this to be safe.
6757+
6758+ // This is safe to call because handle_request is only called by send_
6759+ // which locks the request mutex during the process. It would be a bug
6760+ // to call it from a different thread since it's a thread-safety issue
6761+ // to do these things to the socket if another thread is using the socket.
6762+ std::lock_guard<std::mutex> guard (socket_mutex_);
6763+ shutdown_ssl (socket_, true );
6764+ shutdown_socket (socket_);
6765+ close_socket (socket_);
6766+ }
6767+
67516768 if (300 < res.status && res.status < 400 && follow_location_) {
67526769 req = req_save;
67536770 ret = redirect (req, res, error);
@@ -7162,24 +7179,6 @@ inline bool ClientImpl::process_request(Stream &strm, Request &req,
71627179 }
71637180 }
71647181
7165- if (res.get_header_value (" Connection" ) == " close" ||
7166- (res.version == " HTTP/1.0" && res.reason != " Connection established" )) {
7167- // TODO this requires a not-entirely-obvious chain of calls to be correct
7168- // for this to be safe. Maybe a code refactor (such as moving this out to
7169- // the send function and getting rid of the recursiveness of the mutex)
7170- // could make this more obvious.
7171-
7172- // This is safe to call because process_request is only called by
7173- // handle_request which is only called by send, which locks the request
7174- // mutex during the process. It would be a bug to call it from a different
7175- // thread since it's a thread-safety issue to do these things to the socket
7176- // if another thread is using the socket.
7177- std::lock_guard<std::mutex> guard (socket_mutex_);
7178- shutdown_ssl (socket_, true );
7179- shutdown_socket (socket_);
7180- close_socket (socket_);
7181- }
7182-
71837182 // Log
71847183 if (logger_) { logger_ (req, res); }
71857184
@@ -8287,14 +8286,14 @@ inline bool SSLClient::create_and_connect_socket(Socket &socket, Error &error) {
82878286inline bool SSLClient::connect_with_proxy (Socket &socket, Response &res,
82888287 bool &success, Error &error) {
82898288 success = true ;
8290- Response res2 ;
8289+ Response proxy_res ;
82918290 if (!detail::process_client_socket (
82928291 socket.sock , read_timeout_sec_, read_timeout_usec_,
82938292 write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) {
82948293 Request req2;
82958294 req2.method = " CONNECT" ;
82968295 req2.path = host_and_port_;
8297- return process_request (strm, req2, res2 , false , error);
8296+ return process_request (strm, req2, proxy_res , false , error);
82988297 })) {
82998298 // Thread-safe to close everything because we are assuming there are no
83008299 // requests in flight
@@ -8305,12 +8304,12 @@ inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res,
83058304 return false ;
83068305 }
83078306
8308- if (res2 .status == 407 ) {
8307+ if (proxy_res .status == 407 ) {
83098308 if (!proxy_digest_auth_username_.empty () &&
83108309 !proxy_digest_auth_password_.empty ()) {
83118310 std::map<std::string, std::string> auth;
8312- if (detail::parse_www_authenticate (res2 , auth, true )) {
8313- Response res3 ;
8311+ if (detail::parse_www_authenticate (proxy_res , auth, true )) {
8312+ proxy_res = Response () ;
83148313 if (!detail::process_client_socket (
83158314 socket.sock , read_timeout_sec_, read_timeout_usec_,
83168315 write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) {
@@ -8321,7 +8320,7 @@ inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res,
83218320 req3, auth, 1 , detail::random_string (10 ),
83228321 proxy_digest_auth_username_, proxy_digest_auth_password_,
83238322 true ));
8324- return process_request (strm, req3, res3 , false , error);
8323+ return process_request (strm, req3, proxy_res , false , error);
83258324 })) {
83268325 // Thread-safe to close everything because we are assuming there are
83278326 // no requests in flight
@@ -8332,12 +8331,24 @@ inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res,
83328331 return false ;
83338332 }
83348333 }
8335- } else {
8336- res = res2;
8337- return false ;
83388334 }
83398335 }
83408336
8337+ // If status code is not 200, proxy request is failed.
8338+ // Set error to ProxyConnection and return proxy response
8339+ // as the response of the request
8340+ if (proxy_res.status != 200 )
8341+ {
8342+ error = Error::ProxyConnection;
8343+ res = std::move (proxy_res);
8344+ // Thread-safe to close everything because we are assuming there are
8345+ // no requests in flight
8346+ shutdown_ssl (socket, true );
8347+ shutdown_socket (socket);
8348+ close_socket (socket);
8349+ return false ;
8350+ }
8351+
83418352 return true ;
83428353}
83438354
0 commit comments