always generate Date and Content-Length headers for HTTP/1.1

svn:r564
This commit is contained in:
Niels Provos 2007-11-29 06:08:24 +00:00
parent f175befac9
commit 74b3db50ae
3 changed files with 110 additions and 38 deletions

View File

@ -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:

82
http.c
View File

@ -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");
}
}

View 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
*/