Skip to content

Commit

Permalink
fix http client close during req callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
ekoby committed Oct 8, 2024
1 parent 26e3167 commit 3fb4a77
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 46 deletions.
1 change: 1 addition & 0 deletions include/tlsuv/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ struct tlsuv_http_s {
um_header_list headers;

int connected;
bool keepalive;
tlsuv_src_t *src;
bool own_src;

Expand Down
72 changes: 27 additions & 45 deletions src/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,51 +81,18 @@ static void http_read_cb(uv_link_t *link, ssize_t nread, const uv_buf_t *buf) {

close_connection(c);
uv_async_send(&c->proc);
if (buf && buf->base) {
tlsuv__free(buf->base);
}
return;
}

if (c->active != NULL) {

if (nread > 0) {
} else if (nread > 0) {
if (c->active != NULL) {
if (http_req_process(c->active, buf->base, nread) < 0) {
UM_LOG(WARN, "failed to parse HTTP response");
fail_active_request(c, UV_EINVAL, "failed to parse HTTP response");
close_connection(c);
tlsuv__free(buf->base);
return;
}
}

if (c->active->state == completed) {
tlsuv_http_req_t *hr = c->active;
c->active = NULL;

bool keep_alive = true;
const char *keep_alive_hdr = tlsuv_http_resp_header(&hr->resp, "Connection");
if (strcmp(hr->resp.http_version, "1.1") == 0) {
if (keep_alive_hdr && strcasecmp("close", keep_alive_hdr) == 0)
keep_alive = false;
} else if (strcmp(hr->resp.http_version, "1.0") == 0) {
keep_alive = keep_alive_hdr && strcasecmp("keep-alive", keep_alive_hdr) == 0;
} else {
UM_LOG(WARN, "unexpected HTTP version(%s)", hr->resp.http_version);
keep_alive = false;
}

http_req_free(hr);
tlsuv__free(hr);

if (!keep_alive) {
close_connection(c);
} else {
uv_async_send(&c->proc);
}
uv_async_send(&c->proc);
} else {
UM_LOG(ERR, "received %zd bytes without active request", nread);
}
} else if (nread > 0) {
UM_LOG(ERR, "received %zd bytes without active request", nread);
}

if (buf && buf->base) {
Expand All @@ -148,15 +115,24 @@ static void clear_req_body(tlsuv_http_req_t *req, int code) {
}

static void fail_active_request(tlsuv_http_t *c, int code, const char *msg) {
if (c->active != NULL && c->active->resp_cb != NULL) {
if (c->active == NULL) return;

// this is called from active request callback
if (c->active->state == completed) return;

if (c->active->resp_cb != NULL) {
c->active->resp.code = code;
c->active->resp.status = tlsuv__strdup(msg);
c->active->resp_cb(&c->active->resp, c->active->data);
clear_req_body(c->active, code);
http_req_free(c->active);
tlsuv__free(c->active);
c->active = NULL;
c->active->resp_cb = NULL;
} else if (c->active->resp.body_cb != NULL) {
c->active->resp.body_cb(c->active, NULL, code);
}

clear_req_body(c->active, code);
http_req_free(c->active);
tlsuv__free(c->active);
c->active = NULL;
}

static void fail_all_requests(tlsuv_http_t *c, int code, const char *msg) {
Expand Down Expand Up @@ -395,6 +371,11 @@ static void process_requests(uv_async_t *ar) {
if (c->active == NULL && !STAILQ_EMPTY(&c->requests)) {
c->active = STAILQ_FIRST(&c->requests);
STAILQ_REMOVE_HEAD(&c->requests, _next);

// if not keepalive close connection before next request
if (!c->keepalive) {
close_connection(c);
}
}

if (c->active == NULL) {
Expand Down Expand Up @@ -656,8 +637,9 @@ int http_req_cancel_err(tlsuv_http_t *clt, tlsuv_http_req_t *req, int error, con
req->resp.status = tlsuv__strdup(msg ? msg : uv_strerror(error));
clear_req_body(req, req->resp.code);

if (req->state < headers_received) { // resp_cb has not been called yet
req->resp_cb(&r->resp, r->data);
if (req->state < headers_received && req->resp_cb) { // resp_cb has not been called yet
req->resp_cb(&req->resp, req->data);
req->resp_cb = NULL;
} else if (req->resp.body_cb) {
req->resp.body_cb(req, NULL, req->resp.code);
}
Expand Down
16 changes: 15 additions & 1 deletion src/http_req.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ static int http_status_cb(llhttp_t *parser, const char *status, size_t len) {
tlsuv_http_req_t *r = parser->data;
r->resp.code = (int) parser->status_code;
snprintf(r->resp.http_version, sizeof(r->resp.http_version), "%1d.%1d", parser->http_major, parser->http_minor);
r->client->keepalive = !(parser->http_major == 1 && parser->http_minor == 0);
r->resp.status = tlsuv__calloc(1, len+1);
strncpy(r->resp.status, status, len);
return 0;
Expand All @@ -370,6 +371,18 @@ static int http_message_cb(llhttp_t *parser) {
UM_LOG(VERB, "message complete");
tlsuv_http_req_t *r = parser->data;
r->state = completed;
tlsuv_http_t *client = r->client;

const char *keep_alive_hdr = tlsuv_http_resp_header(&r->resp, "Connection");

if (keep_alive_hdr) {
r->client->keepalive = strcasecmp(keep_alive_hdr, "close") != 0;
}

if (client->active == r) {
client->active = NULL;
}

if (r->resp.body_cb) {
if (r->inflater == NULL || um_inflate_state(r->inflater) == 1) {
r->resp.body_cb(r, NULL, UV_EOF);
Expand All @@ -378,7 +391,8 @@ static int http_message_cb(llhttp_t *parser) {
r->resp.body_cb(r, NULL, UV_EINVAL);
}
}

http_req_free(r);
tlsuv__free(r);
return 0;
}

Expand Down

0 comments on commit 3fb4a77

Please sign in to comment.