From: Niels Provos Date: Thu, 29 Nov 2007 06:08:24 +0000 (+0000) Subject: always generate Date and Content-Length headers for HTTP/1.1 X-Git-Tag: release-2.0.1-alpha~475 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=74b3db50ae9cdbc9ffcafd761251935d7f1a2216;p=libevent always generate Date and Content-Length headers for HTTP/1.1 svn:r564 --- diff --git a/ChangeLog b/ChangeLog index 8c993cfc..bef5d050 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,7 @@ Changes in current version: o The configure script now takes an --enable-gcc-warnigns option that turns on many optional gcc warnings. (Nick has been building with these for a while, but they might be useful to other developers.) o move EV_PERSIST handling out of the event backends o small improvements to evhttp documentation + o always generate Date and Content-Length headers for HTTP/1.1 replies Changes in 1.4.0: diff --git a/http.c b/http.c index f0f1f6c8..38c0379d 100644 --- a/http.c +++ b/http.c @@ -302,7 +302,7 @@ evhttp_write_buffer(struct evhttp_connection *evcon, } /* - * Create the headers need for an HTTP reply + * Create the headers need for an HTTP request */ static void evhttp_make_header_request(struct evhttp_connection *evcon, @@ -351,9 +351,45 @@ evhttp_is_connection_keepalive(struct evkeyvalq* headers) && strncasecmp(connection, "keep-alive", 10) == 0); } +static void +evhttp_maybe_add_date_header(struct evkeyvalq *headers) +{ + if (evhttp_find_header(headers, "Date") == NULL) { + char date[50]; +#ifndef WIN32 + struct tm cur; +#endif + struct tm *cur_p; + time_t t = time(NULL); +#ifdef WIN32 + cur_p = gmtime(&t); +#else + gmtime_r(&t, &cur); + cur_p = &cur; +#endif + if (strftime(date, sizeof(date), + "%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) { + evhttp_add_header(headers, "Date", date); + } + } +} + +static void +evhttp_maybe_add_content_length_header(struct evkeyvalq *headers, + long content_length) +{ + if (evhttp_find_header(headers, "Transfer-Encoding") == NULL && + evhttp_find_header(headers, "Content-Length") == NULL) { + static char len[12]; /* XXX: not thread-safe */ + snprintf(len, sizeof(len), "%ld", content_length); + evhttp_add_header(headers, "Content-Length", len); + } +} + /* * Create the headers needed for an HTTP reply */ + static void evhttp_make_header_response(struct evhttp_connection *evcon, struct evhttp_request *req) @@ -364,48 +400,24 @@ evhttp_make_header_response(struct evhttp_connection *evcon, req->response_code_line); evbuffer_add(evcon->output_buffer, line, strlen(line)); - /* Potentially add headers for unidentified content. */ - if (EVBUFFER_LENGTH(req->output_buffer)) { - if (evhttp_find_header(req->output_headers, - "Date") == NULL) { - char date[50]; -#ifndef WIN32 - struct tm cur; -#endif - struct tm *cur_p; - time_t t = time(NULL); -#ifdef WIN32 - cur_p = gmtime(&t); -#else - gmtime_r(&t, &cur); - cur_p = &cur; -#endif - if (strftime(date, sizeof(date), - "%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) { - evhttp_add_header(req->output_headers, "Date", date); - } - } - - if (evhttp_find_header(req->output_headers, - "Content-Type") == NULL) { - evhttp_add_header(req->output_headers, - "Content-Type", "text/html; charset=ISO-8859-1"); - } + if (req->major == 1 && req->minor == 1) { + evhttp_maybe_add_date_header(req->output_headers); /* * we need to add the content length if the user did * not give it, this is required for persistent * connections to work. */ + evhttp_maybe_add_content_length_header(req->output_headers, + (long)EVBUFFER_LENGTH(req->output_buffer)); + } + + /* Potentially add headers for unidentified content. */ + if (EVBUFFER_LENGTH(req->output_buffer)) { if (evhttp_find_header(req->output_headers, - "Transfer-Encoding") == NULL && - evhttp_find_header(req->output_headers, - "Content-Length") == NULL) { - static char len[12]; - snprintf(len, sizeof(len), "%ld", - (long)EVBUFFER_LENGTH(req->output_buffer)); + "Content-Type") == NULL) { evhttp_add_header(req->output_headers, - "Content-Length", len); + "Content-Type", "text/html; charset=ISO-8859-1"); } } diff --git a/test/regress_http.c b/test/regress_http.c index 97f25fc3..05c7da0d 100644 --- a/test/regress_http.c +++ b/test/regress_http.c @@ -200,12 +200,14 @@ http_errorcb(struct bufferevent *bev, short what, void *arg) void http_basic_cb(struct evhttp_request *req, void *arg) { - struct evbuffer *evb = evbuffer_new(); + int empty = evhttp_find_header(req->input_headers, "Empty") != NULL; event_debug(("%s: called\n", __func__)); evbuffer_add_printf(evb, "This is funny"); - evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); + /* allow sending of an empty reply */ + evhttp_send_reply(req, HTTP_OK, "Everything is fine", + !empty ? evb : NULL); evbuffer_free(evb); } @@ -253,6 +255,7 @@ http_basic_test(void) } void http_request_done(struct evhttp_request *, void *); +void http_request_empty_done(struct evhttp_request *, void *); static void http_connection_test(int persistent) @@ -319,6 +322,27 @@ http_connection_test(int persistent) event_dispatch(); + /* make another request: request empty reply */ + test_ok = 0; + + req = evhttp_request_new(http_request_empty_done, NULL); + + /* Add the information that we care about */ + evhttp_add_header(req->output_headers, "Empty", "itis"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + event_dispatch(); + + if (test_ok != 1) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + evhttp_connection_free(evcon); evhttp_free(http); @@ -331,7 +355,6 @@ http_request_done(struct evhttp_request *req, void *arg) const char *what = "This is funny"; if (req->response_code != HTTP_OK) { - fprintf(stderr, "FAILED\n"); exit(1); } @@ -355,6 +378,42 @@ http_request_done(struct evhttp_request *req, void *arg) event_loopexit(NULL); } +/* test date header and content length */ + +void +http_request_empty_done(struct evhttp_request *req, void *arg) +{ + if (req->response_code != HTTP_OK) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (evhttp_find_header(req->input_headers, "Date") == NULL) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + + if (evhttp_find_header(req->input_headers, "Content-Length") == NULL) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (strcmp(evhttp_find_header(req->input_headers, "Content-Length"), + "0")) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (EVBUFFER_LENGTH(req->input_buffer) != 0) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + test_ok = 1; + event_loopexit(NULL); +} + /* * HTTP DISPATCHER test */