From 08bb8f7c232c131cba8faf4160f5768f9d7ae838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Tue, 15 Sep 2009 22:59:59 +0200 Subject: [PATCH] Some request handling bugs (keep-alive, content-length, pipelining) --- src/main/connection.c | 48 +++++++++++++++++++++++---------------- src/main/request.c | 2 ++ src/main/virtualrequest.c | 9 ++++++-- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/main/connection.c b/src/main/connection.c index 16d92d1..701798e 100644 --- a/src/main/connection.c +++ b/src/main/connection.c @@ -13,7 +13,8 @@ static void parse_request_body(liConnection *con) { li_ev_io_add_events(con->wrk->loop, &con->sock_watcher, EV_READ); if (con->mainvr->request.content_length == -1) { /* TODO: parse chunked encoded request body, filters */ - li_chunkqueue_steal_all(con->in, con->raw_in); + /* li_chunkqueue_steal_all(con->in, con->raw_in); */ + con->in->is_closed = TRUE; } else { if (con->in->bytes_in < con->mainvr->request.content_length) { li_chunkqueue_steal_len(con->in, con->raw_in, con->mainvr->request.content_length - con->in->bytes_in); @@ -587,24 +588,28 @@ void li_connection_reset(liConnection *con) { static void li_connection_reset_keep_alive(liConnection *con) { liVRequest *vr = con->mainvr; - ev_timer_stop(con->wrk->loop, &con->keep_alive_data.watcher); - { - con->keep_alive_data.max_idle = CORE_OPTION(LI_CORE_OPTION_MAX_KEEP_ALIVE_IDLE).number; - if (con->keep_alive_data.max_idle == 0) { - worker_con_put(con); - return; - } - if (con->keep_alive_data.max_idle >= con->srv->keep_alive_queue_timeout) { - /* queue is sorted by con->keep_alive_data.timeout */ - gboolean need_start = (0 == con->wrk->keep_alive_queue.length); - con->keep_alive_data.timeout = ev_now(con->wrk->loop) + con->srv->keep_alive_queue_timeout; - g_queue_push_tail(&con->wrk->keep_alive_queue, con); - con->keep_alive_data.link = g_queue_peek_tail_link(&con->wrk->keep_alive_queue); - if (need_start) - li_worker_check_keepalive(con->wrk); - } else { - ev_timer_set(&con->keep_alive_data.watcher, con->keep_alive_data.max_idle, 0); - ev_timer_start(con->wrk->loop, &con->keep_alive_data.watcher); + + /* only start keep alive watcher if there isn't more input data already */ + if (con->raw_in->length == 0) { + ev_timer_stop(con->wrk->loop, &con->keep_alive_data.watcher); + { + con->keep_alive_data.max_idle = CORE_OPTION(LI_CORE_OPTION_MAX_KEEP_ALIVE_IDLE).number; + if (con->keep_alive_data.max_idle == 0) { + worker_con_put(con); + return; + } + if (con->keep_alive_data.max_idle >= con->srv->keep_alive_queue_timeout) { + /* queue is sorted by con->keep_alive_data.timeout */ + gboolean need_start = (0 == con->wrk->keep_alive_queue.length); + con->keep_alive_data.timeout = ev_now(con->wrk->loop) + con->srv->keep_alive_queue_timeout; + g_queue_push_tail(&con->wrk->keep_alive_queue, con); + con->keep_alive_data.link = g_queue_peek_tail_link(&con->wrk->keep_alive_queue); + if (need_start) + li_worker_check_keepalive(con->wrk); + } else { + ev_timer_set(&con->keep_alive_data.watcher, con->keep_alive_data.max_idle, 0); + ev_timer_start(con->wrk->loop, &con->keep_alive_data.watcher); + } } } @@ -669,6 +674,11 @@ static void li_connection_reset_keep_alive(liConnection *con) { con->throttle.ip.magazine = 0; con->throttle.con.magazine = 0; con->throttled = FALSE; + + if (con->raw_in->length != 0) { + /* start handling next request if data is already available */ + connection_handle_read(con); + } } void li_connection_free(liConnection *con) { diff --git a/src/main/request.c b/src/main/request.c index b0b581d..0c5563e 100644 --- a/src/main/request.c +++ b/src/main/request.c @@ -248,6 +248,8 @@ gboolean li_request_validate_header(liConnection *con) { } break; default: + if (con->mainvr->request.content_length == -1) + con->mainvr->request.content_length = 0; /* the may have a content-length */ break; } diff --git a/src/main/virtualrequest.c b/src/main/virtualrequest.c index 82a72ee..dcaef08 100644 --- a/src/main/virtualrequest.c +++ b/src/main/virtualrequest.c @@ -416,8 +416,13 @@ void li_vrequest_state_machine(liVRequest *vr) { switch (res) { case LI_HANDLER_GO_ON: if (vr->state == LI_VRS_HANDLE_REQUEST_HEADERS) { - /* unhandled request */ - vr->response.http_status = 404; + if (vr->request.http_method == LI_HTTP_METHOD_OPTIONS) { + vr->response.http_status = 200; + li_http_header_append(vr->response.headers, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST")); + } else { + /* unhandled request */ + vr->response.http_status = 404; + } li_vrequest_handle_direct(vr); } break;