diff --git a/include/modules/http.h b/include/modules/http.h index fe24aed..a11f3c6 100644 --- a/include/modules/http.h +++ b/include/modules/http.h @@ -13,6 +13,13 @@ typedef struct ant_http_header_s { struct ant_http_header_s *next; } ant_http_header_t; +typedef enum { + ANT_HTTP_RESULT_OK = 0, + ANT_HTTP_RESULT_NETWORK_ERROR, + ANT_HTTP_RESULT_ABORTED, + ANT_HTTP_RESULT_PROTOCOL_ERROR, +} ant_http_result_t; + typedef struct { const char *method; const char *url; @@ -43,6 +50,7 @@ typedef void (*ant_http_body_cb)( typedef void (*ant_http_complete_cb)( ant_http_request_t *req, + ant_http_result_t result, int error_code, const char *error_message, void *user_data diff --git a/src/modules/fetch.c b/src/modules/fetch.c index 0a921a4..12a5986 100644 --- a/src/modules/fetch.c +++ b/src/modules/fetch.c @@ -40,6 +40,7 @@ typedef struct fetch_request_s { int refs; bool settled; bool aborted; + bool response_started; } fetch_request_t; static UT_array *pending_requests = NULL; @@ -118,6 +119,7 @@ static void fetch_reject(fetch_request_t *req, ant_value_t reason) { static void fetch_resolve(fetch_request_t *req, ant_value_t response_obj) { if (!req || req->settled) return; req->settled = true; + req->response_started = true; req->response_obj = response_obj; js_resolve_promise(req->js, req->promise, response_obj); } @@ -344,18 +346,30 @@ static void fetch_http_on_body(ant_http_request_t *http_req, const uint8_t *chun } } -static void fetch_http_on_complete(ant_http_request_t *http_req, int error_code, const char *error_message, void *user_data) { +static ant_value_t fetch_transport_reason(fetch_request_t *req, ant_http_result_t result, const char *error_message) { + if (result == ANT_HTTP_RESULT_ABORTED && req->aborted) { + ant_value_t signal = request_get_signal(req->request_obj); + return abort_signal_get_reason(signal); + } + + return fetch_type_error(req->js, error_message ? error_message : "fetch failed"); +} + +static void fetch_http_on_complete( + ant_http_request_t *http_req, + ant_http_result_t result, + int error_code, const char *error_message, void *user_data +) { fetch_request_t *req = (fetch_request_t *)user_data; + ant_t *js = req->js; ant_value_t stream = 0; ant_value_t controller = 0; ant_value_t reason = 0; - - (void)http_req; req->http_req = NULL; - if (error_code != 0) { - reason = fetch_type_error(js, error_message ? error_message : "fetch failed"); + if (result != ANT_HTTP_RESULT_OK || error_code != 0) { + reason = fetch_transport_reason(req, result, error_message); if (is_object_type(req->response_obj)) fetch_error_response_body(req, reason); else fetch_reject(req, reason); fetch_request_release(req); diff --git a/src/modules/http.c b/src/modules/http.c index 274c518..ee49ace 100644 --- a/src/modules/http.c +++ b/src/modules/http.c @@ -20,8 +20,11 @@ struct ant_http_request_s { char *error_message; brotli_stream_state_t *brotli_decoder; + ant_http_result_t result; int error_code; + bool completed; + bool canceled; bool decode_brotli; }; @@ -141,7 +144,7 @@ static void ant_http_on_close(tlsuv_http_t *client) { if (!req) return; if (req->on_complete) req->on_complete( - req, req->error_code, + req, req->result, req->error_code, req->error_message, req->user_data ); @@ -153,6 +156,10 @@ static void ant_http_complete(ant_http_request_t *req, int error_code, const cha if (!req || req->completed) return; req->completed = 1; req->error_code = error_code; + + if (error_code == 0) req->result = ANT_HTTP_RESULT_OK; + else if (req->canceled) req->result = ANT_HTTP_RESULT_ABORTED; + else req->result = ANT_HTTP_RESULT_NETWORK_ERROR; free(req->error_message); req->error_message = error_message ? strdup(error_message) : NULL; @@ -237,6 +244,7 @@ const ant_http_response_t *ant_http_request_response(ant_http_request_t *req) { int ant_http_request_cancel(ant_http_request_t *req) { if (!req || !req->req || req->completed) return 0; + req->canceled = true; return tlsuv_http_req_cancel(&req->client, req->req); }