@@ -40,20 +40,48 @@ namespace web { namespace http
4040 class linux_client ;
4141 struct client ;
4242
43+ enum class httpclient_errorcode_context
44+ {
45+ none = 0 ,
46+ connect,
47+ writeheader,
48+ writebody,
49+ readheader,
50+ readbody,
51+ close
52+ };
4353 class linux_request_context : public request_context
44- {
54+ {
4555 public:
4656 static request_context * create_request_context (std::shared_ptr<_http_client_communicator> &client, http_request &request)
4757 {
4858 return new linux_request_context (client, request);
4959 }
5060
51- void report_error (const utility::string_t &scope , boost::system::error_code ec)
61+ void report_error (const utility::string_t &message , boost::system::error_code ec, httpclient_errorcode_context context = httpclient_errorcode_context::none )
5262 {
53- if (ec.default_error_condition ().value () == boost::system::errc::operation_canceled && m_timedout)
54- request_context::report_error (boost::system::errc::timed_out, scope);
55- else
56- request_context::report_error (ec.default_error_condition ().value (), scope);
63+ // By default, errorcodeValue don't need to converted
64+ long errorcodeValue = ec.value ();
65+
66+ // map timer cancellation to time_out
67+ if (ec == boost::system::errc::operation_canceled && m_timedout)
68+ errorcodeValue = make_error_code (std::errc::timed_out).value ();
69+ else
70+ {
71+ // We need to correct inaccurate ASIO error code base on context information
72+ switch (context)
73+ {
74+ case httpclient_errorcode_context::connect:
75+ if (ec == boost::system::errc::connection_refused)
76+ errorcodeValue = make_error_code (std::errc::host_unreachable).value ();
77+ break ;
78+ case httpclient_errorcode_context::readheader:
79+ if (ec.default_error_condition ().value () == boost::system::errc::no_such_file_or_directory) // bug in boost error_code mapping
80+ errorcodeValue = make_error_code (std::errc::connection_aborted).value ();
81+ break ;
82+ }
83+ }
84+ request_context::report_error (errorcodeValue, message);
5785 }
5886
5987 std::unique_ptr<tcp::socket> m_socket;
@@ -218,7 +246,7 @@ namespace web { namespace http
218246 {
219247 if (ec)
220248 {
221- ctx->report_error (" Error resolving address" , ec);
249+ ctx->report_error (" Error resolving address" , ec, httpclient_errorcode_context::connect );
222250 }
223251 else
224252 {
@@ -235,7 +263,7 @@ namespace web { namespace http
235263 }
236264 else if (endpoints == tcp::resolver::iterator ())
237265 {
238- ctx->report_error (" Failed to connect to any resolved endpoint" , ec);
266+ ctx->report_error (" Failed to connect to any resolved endpoint" , ec, httpclient_errorcode_context::connect );
239267 }
240268 else
241269 {
@@ -326,7 +354,7 @@ namespace web { namespace http
326354 }
327355 else
328356 {
329- ctx->report_error (" Failed to write request headers" , ec);
357+ ctx->report_error (" Failed to write request headers" , ec, httpclient_errorcode_context::writeheader );
330358 }
331359 }
332360
@@ -346,7 +374,7 @@ namespace web { namespace http
346374 }
347375 else
348376 {
349- ctx->report_error (" Failed to write request body" , ec);
377+ ctx->report_error (" Failed to write request body" , ec, httpclient_errorcode_context::writebody );
350378 }
351379 }
352380
@@ -370,15 +398,15 @@ namespace web { namespace http
370398
371399 if (!response_stream || http_version.substr (0 , 5 ) != " HTTP/" )
372400 {
373- ctx->report_error (" Invalid HTTP status line" , ec);
401+ ctx->report_error (" Invalid HTTP status line" , ec, httpclient_errorcode_context::readheader );
374402 return ;
375403 }
376404
377405 read_headers (ctx);
378406 }
379407 else
380408 {
381- ctx->report_error (" Failed to read HTTP status line" , ec);
409+ ctx->report_error (" Failed to read HTTP status line" , ec, httpclient_errorcode_context::readheader );
382410 }
383411 }
384412
@@ -458,15 +486,15 @@ namespace web { namespace http
458486
459487 if (octetLine.fail ())
460488 {
461- ctx->report_error (" Invalid chunked response header" , boost::system::error_code ());
489+ ctx->report_error (" Invalid chunked response header" , boost::system::error_code (), httpclient_errorcode_context::readbody );
462490 }
463491 else
464492 async_read_until_buffersize (octets + CRLF.size (), // +2 for crlf
465493 boost::bind (&client::handle_chunk, this , boost::asio::placeholders::error, octets, ctx), ctx);
466494 }
467495 else
468496 {
469- ctx->report_error (" Retrieving message chunk header" , ec);
497+ ctx->report_error (" Retrieving message chunk header" , ec, httpclient_errorcode_context::readbody );
470498 }
471499 }
472500
@@ -516,7 +544,7 @@ namespace web { namespace http
516544 }
517545 else
518546 {
519- ctx->report_error (" Failed to read chunked response part" , ec);
547+ ctx->report_error (" Failed to read chunked response part" , ec, httpclient_errorcode_context::readbody );
520548 }
521549 }
522550
@@ -526,7 +554,7 @@ namespace web { namespace http
526554
527555 if (ec)
528556 {
529- ctx->report_error (" Failed to read response body" , ec);
557+ ctx->report_error (" Failed to read response body" , ec, httpclient_errorcode_context::readbody );
530558 return ;
531559 }
532560 auto progress = ctx->m_request ._get_impl ()->_progress_handler ();
0 commit comments