]> granicus.if.org Git - libevent/commitdiff
always generate Date and Content-Length headers for HTTP/1.1
authorNiels Provos <provos@gmail.com>
Thu, 29 Nov 2007 06:08:24 +0000 (06:08 +0000)
committerNiels Provos <provos@gmail.com>
Thu, 29 Nov 2007 06:08:24 +0000 (06:08 +0000)
svn:r564

ChangeLog
http.c
test/regress_http.c

index 8c993cfc85c8b7b01e0a6f22bc18bc9106f3bc52..bef5d050fd84483cf27d4464c852b2b02517f2b8 100644 (file)
--- 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 f0f1f6c81c046d459386845e075eb39419653983..38c0379deb6c58d97f3f7e2dbbec31af6cbc5eba 100644 (file)
--- 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");
                }
        }
 
index 97f25fc390284e2ba4e49fef8203a2b9ba6632ef..05c7da0defb4f30940152da221f7869adcfba4d2 100644 (file)
@@ -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
  */