From 67ed0bce433655dfeab65b797279dd167b394feb Mon Sep 17 00:00:00 2001 From: Mark Ellzey Date: Tue, 24 Mar 2015 18:48:46 -0400 Subject: [PATCH] Issue161 : deal with http 1.0 stuff --- evhtp.c | 33 +++++++++++++++++---------------- evhtp.h | 4 +++- examples/test_basic.c | 19 +++++++++++++++++++ htparse.c | 23 +++++++++++++++-------- 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/evhtp.c b/evhtp.c index 3a0bf90..e60b9fb 100644 --- a/evhtp.c +++ b/evhtp.c @@ -1637,23 +1637,7 @@ _evhtp_create_reply(evhtp_request_t * request, evhtp_res code) { evhtp_headers_add_header(request->headers_out, evhtp_header_new("Content-Length", out_buf, 0, 1)); } - - if (!content_type) { - evhtp_headers_add_header(request->headers_out, - evhtp_header_new("Content-Type", "text/plain", 0, 0)); - } - } else { - if (!evhtp_header_find(request->headers_out, "Content-Length")) { - const char * chunked = evhtp_header_find(request->headers_out, - "transfer-encoding"); - - if (!chunked || !strstr(chunked, "chunked")) { - evhtp_headers_add_header(request->headers_out, - evhtp_header_new("Content-Length", "0", 0, 0)); - } - } } - check_proto: /* add the proper keep-alive type headers based on http version */ switch (request->proto) { @@ -1680,6 +1664,11 @@ _evhtp_create_reply(evhtp_request_t * request, evhtp_res code) { } /* switch */ + if (!content_type) { + evhtp_headers_add_header(request->headers_out, + evhtp_header_new("Content-Type", "text/plain", 0, 0)); + } + /* attempt to add the status line into a temporary buffer and then use * evbuffer_add(). Using plain old snprintf() will be faster than * evbuffer_add_printf(). If the snprintf() fails, which it rarely should, @@ -3052,8 +3041,10 @@ evhtp_send_reply_chunk_start(evhtp_request_t * request, evhtp_res code) { */ evhtp_kv_rm_and_free(request->headers_out, content_len); +#if 0 evhtp_headers_add_header(request->headers_out, evhtp_header_new("Content-Length", "0", 0, 0)); +#endif request->chunked = 1; break; @@ -3879,11 +3870,21 @@ evhtp_request_set_bev(evhtp_request_t * request, evbev_t * bev) { evhtp_connection_set_bev(request->conn, bev); } +void +evhtp_request_set_keepalive(evhtp_request_t * request, int val) { + request->keepalive = (val > 0) ? 1 : 0; +} + evhtp_connection_t * evhtp_request_get_connection(evhtp_request_t * request) { return request->conn; } +evhtp_proto +evhtp_request_get_proto(evhtp_request_t * request) { + return request->proto; +} + inline void evhtp_connection_set_timeouts(evhtp_connection_t * c, const struct timeval * rtimeo, diff --git a/evhtp.h b/evhtp.h index 16b7c9a..1d6b292 100644 --- a/evhtp.h +++ b/evhtp.h @@ -1131,7 +1131,8 @@ EVHTP_EXPORT const char * evhtp_header_find(evhtp_headers_t * headers, const cha * * @return htp_method enum */ -EVHTP_EXPORT htp_method evhtp_request_get_method(evhtp_request_t * r); +EVHTP_EXPORT htp_method evhtp_request_get_method(evhtp_request_t * r); +EVHTP_EXPORT evhtp_proto evhtp_request_get_proto(evhtp_request_t * r); /* the following functions all do the same thing, pause and the processing */ EVHTP_EXPORT void evhtp_connection_pause(evhtp_connection_t * connection); @@ -1247,6 +1248,7 @@ EVHTP_EXPORT void evhtp_connection_set_max_body_size(evhtp_connection_t * conn, * @param len */ EVHTP_EXPORT void evhtp_request_set_max_body_size(evhtp_request_t * request, uint64_t len); +EVHTP_EXPORT void evhtp_request_set_keepalive(evhtp_request_t * request, int val); /** * @brief sets a maximum number of requests that a single connection can make. diff --git a/examples/test_basic.c b/examples/test_basic.c index 2eb3f4f..5f31604 100644 --- a/examples/test_basic.c +++ b/examples/test_basic.c @@ -13,6 +13,24 @@ testcb(evhtp_request_t * req, void * a) { evhtp_send_reply(req, EVHTP_RES_OK); } +void +issue161cb(evhtp_request_t * req, void * a) { + struct evbuffer * b = evbuffer_new(); + + evhtp_request_set_keepalive(req, 0); + evhtp_send_reply_start(req, EVHTP_RES_OK); + + evbuffer_add(b, "foo", 3); + evhtp_send_reply_body(req, b); + + evbuffer_add(b, "bar\n\n", 5); + evhtp_send_reply_body(req, b); + + evhtp_send_reply_end(req); + + evbuffer_free(b); +} + int main(int argc, char ** argv) { evbase_t * evbase = event_base_new(); @@ -21,6 +39,7 @@ main(int argc, char ** argv) { evhtp_set_cb(htp, "/simple/", testcb, "simple"); evhtp_set_cb(htp, "/1/ping", testcb, "one"); evhtp_set_cb(htp, "/1/ping.json", testcb, "two"); + evhtp_set_cb(htp, "/issue161", issue161cb, NULL); #ifndef EVHTP_DISABLE_EVTHR evhtp_use_threads(htp, NULL, 8, NULL); #endif diff --git a/htparse.c b/htparse.c index 855c26d..9fd7d79 100644 --- a/htparse.c +++ b/htparse.c @@ -1628,14 +1628,20 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len) break; case eval_hdr_val_connection: switch (p->buf[0]) { + char A_case = 'A'; + case 'K': case 'k': if (p->buf_idx != 10) { break; } + if (p->buf[5] == 'a') { + A_case = 'a'; + } + if (_str9cmp((p->buf + 1), - 'e', 'e', 'p', '-', 'A', 'l', 'i', 'v', 'e')) { + 'e', 'e', 'p', '-', A_case, 'l', 'i', 'v', 'e')) { p->flags |= parser_flag_connection_keep_alive; } break; @@ -1754,13 +1760,6 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len) return i + 1; } - res = hook_on_hdrs_complete_run(p, hooks); - - if (res) { - p->error = htparse_error_user; - return i + 1; - } - break; case LF: /* got LFLF? is this valid? */ @@ -1796,6 +1795,14 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len) switch (ch) { case LF: + res = hook_on_hdrs_complete_run(p, hooks); + + if (res) { + p->error = htparse_error_user; + return i + 1; + } + + p->buf_idx = 0; htparse_log_debug("[%p] HERE", p);