@@ -40,20 +40,48 @@ namespace web { namespace http
40
40
class linux_client ;
41
41
struct client ;
42
42
43
+ enum class httpclient_errorcode_context
44
+ {
45
+ none = 0 ,
46
+ connect,
47
+ writeheader,
48
+ writebody,
49
+ readheader,
50
+ readbody,
51
+ close
52
+ };
43
53
class linux_request_context : public request_context
44
- {
54
+ {
45
55
public:
46
56
static request_context * create_request_context (std::shared_ptr<_http_client_communicator> &client, http_request &request)
47
57
{
48
58
return new linux_request_context (client, request);
49
59
}
50
60
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 )
52
62
{
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);
57
85
}
58
86
59
87
std::unique_ptr<tcp::socket> m_socket;
@@ -218,7 +246,7 @@ namespace web { namespace http
218
246
{
219
247
if (ec)
220
248
{
221
- ctx->report_error (" Error resolving address" , ec);
249
+ ctx->report_error (" Error resolving address" , ec, httpclient_errorcode_context::connect );
222
250
}
223
251
else
224
252
{
@@ -235,7 +263,7 @@ namespace web { namespace http
235
263
}
236
264
else if (endpoints == tcp::resolver::iterator ())
237
265
{
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 );
239
267
}
240
268
else
241
269
{
@@ -326,7 +354,7 @@ namespace web { namespace http
326
354
}
327
355
else
328
356
{
329
- ctx->report_error (" Failed to write request headers" , ec);
357
+ ctx->report_error (" Failed to write request headers" , ec, httpclient_errorcode_context::writeheader );
330
358
}
331
359
}
332
360
@@ -346,7 +374,7 @@ namespace web { namespace http
346
374
}
347
375
else
348
376
{
349
- ctx->report_error (" Failed to write request body" , ec);
377
+ ctx->report_error (" Failed to write request body" , ec, httpclient_errorcode_context::writebody );
350
378
}
351
379
}
352
380
@@ -370,15 +398,15 @@ namespace web { namespace http
370
398
371
399
if (!response_stream || http_version.substr (0 , 5 ) != " HTTP/" )
372
400
{
373
- ctx->report_error (" Invalid HTTP status line" , ec);
401
+ ctx->report_error (" Invalid HTTP status line" , ec, httpclient_errorcode_context::readheader );
374
402
return ;
375
403
}
376
404
377
405
read_headers (ctx);
378
406
}
379
407
else
380
408
{
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 );
382
410
}
383
411
}
384
412
@@ -458,15 +486,15 @@ namespace web { namespace http
458
486
459
487
if (octetLine.fail ())
460
488
{
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 );
462
490
}
463
491
else
464
492
async_read_until_buffersize (octets + CRLF.size (), // +2 for crlf
465
493
boost::bind (&client::handle_chunk, this , boost::asio::placeholders::error, octets, ctx), ctx);
466
494
}
467
495
else
468
496
{
469
- ctx->report_error (" Retrieving message chunk header" , ec);
497
+ ctx->report_error (" Retrieving message chunk header" , ec, httpclient_errorcode_context::readbody );
470
498
}
471
499
}
472
500
@@ -516,7 +544,7 @@ namespace web { namespace http
516
544
}
517
545
else
518
546
{
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 );
520
548
}
521
549
}
522
550
@@ -526,7 +554,7 @@ namespace web { namespace http
526
554
527
555
if (ec)
528
556
{
529
- ctx->report_error (" Failed to read response body" , ec);
557
+ ctx->report_error (" Failed to read response body" , ec, httpclient_errorcode_context::readbody );
530
558
return ;
531
559
}
532
560
auto progress = ctx->m_request ._get_impl ()->_progress_handler ();
0 commit comments