mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-10 13:04:23 -04:00
support multi-line http headers; based on a patch from Moshe Litvin
svn:r890
This commit is contained in:
parent
9998c0cbc8
commit
cb7c3bd671
@ -112,6 +112,7 @@ Changes in current version:
|
|||||||
o Do not use SO_REUSEADDR when connecting
|
o Do not use SO_REUSEADDR when connecting
|
||||||
o Support 64-bit integers in RPC structs
|
o Support 64-bit integers in RPC structs
|
||||||
o Correct handling of trailing headers in chunked replies; from Scott Lamb.
|
o Correct handling of trailing headers in chunked replies; from Scott Lamb.
|
||||||
|
o Support multi-line HTTP headers; based on a patch from Moshe Litvin
|
||||||
|
|
||||||
Changes in 1.4.0:
|
Changes in 1.4.0:
|
||||||
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
|
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
|
||||||
|
30
http.c
30
http.c
@ -1412,6 +1412,29 @@ evhttp_parse_firstline(struct evhttp_request *req, struct evbuffer *buffer)
|
|||||||
return (status);
|
return (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
evhttp_append_to_last_header(struct evkeyvalq *headers, const char *line)
|
||||||
|
{
|
||||||
|
struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
|
||||||
|
char *newval;
|
||||||
|
size_t old_len, line_len;
|
||||||
|
|
||||||
|
if (header == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
old_len = strlen(header->value);
|
||||||
|
line_len = strlen(line);
|
||||||
|
|
||||||
|
newval = mm_realloc(header->value, old_len + line_len + 1);
|
||||||
|
if (newval == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
memcpy(newval + old_len, line, line_len + 1);
|
||||||
|
header->value = newval;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
enum message_read_status
|
enum message_read_status
|
||||||
evhttp_parse_headers(struct evhttp_request *req, struct evbuffer* buffer)
|
evhttp_parse_headers(struct evhttp_request *req, struct evbuffer* buffer)
|
||||||
{
|
{
|
||||||
@ -1429,6 +1452,13 @@ evhttp_parse_headers(struct evhttp_request *req, struct evbuffer* buffer)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if this is a continuation line */
|
||||||
|
if (*line == ' ' || *line == '\t') {
|
||||||
|
if (evhttp_append_to_last_header(headers, line) == -1)
|
||||||
|
goto error;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Processing of header lines */
|
/* Processing of header lines */
|
||||||
svalue = line;
|
svalue = line;
|
||||||
skey = strsep(&svalue, ":");
|
skey = strsep(&svalue, ":");
|
||||||
|
@ -232,6 +232,17 @@ http_basic_cb(struct evhttp_request *req, void *arg)
|
|||||||
event_debug(("%s: called\n", __func__));
|
event_debug(("%s: called\n", __func__));
|
||||||
evbuffer_add_printf(evb, "This is funny");
|
evbuffer_add_printf(evb, "This is funny");
|
||||||
|
|
||||||
|
/* For multi-line headers test */
|
||||||
|
{
|
||||||
|
const char *multi =
|
||||||
|
evhttp_find_header(req->input_headers,"X-multi");
|
||||||
|
if (multi) {
|
||||||
|
if (strcmp("END", multi + strlen(multi) - 3) == 0)
|
||||||
|
test_ok++;
|
||||||
|
if (evhttp_find_header(req->input_headers, "X-Last"))
|
||||||
|
test_ok++;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* allow sending of an empty reply */
|
/* allow sending of an empty reply */
|
||||||
evhttp_send_reply(req, HTTP_OK, "Everything is fine",
|
evhttp_send_reply(req, HTTP_OK, "Everything is fine",
|
||||||
!empty ? evb : NULL);
|
!empty ? evb : NULL);
|
||||||
@ -2126,6 +2137,52 @@ failed:
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
http_multi_line_header_test(void)
|
||||||
|
{
|
||||||
|
struct bufferevent *bev;
|
||||||
|
int fd;
|
||||||
|
const char *http_start_request;
|
||||||
|
short port = -1;
|
||||||
|
|
||||||
|
test_ok = 0;
|
||||||
|
fprintf(stdout, "Testing HTTP Server with multi line: ");
|
||||||
|
|
||||||
|
http = http_setup(&port, NULL);
|
||||||
|
|
||||||
|
fd = http_connect("127.0.0.1", port);
|
||||||
|
|
||||||
|
/* Stupid thing to send a request */
|
||||||
|
bev = bufferevent_new(fd, http_readcb, http_writecb,
|
||||||
|
http_errorcb, NULL);
|
||||||
|
|
||||||
|
http_start_request =
|
||||||
|
"GET /test HTTP/1.1\r\n"
|
||||||
|
"Host: somehost\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"X-Multi: aaaaaaaa\r\n"
|
||||||
|
" a\r\n"
|
||||||
|
"\tEND\r\n"
|
||||||
|
"X-Last: last\r\n"
|
||||||
|
"\r\n";
|
||||||
|
|
||||||
|
bufferevent_write(bev, http_start_request, strlen(http_start_request));
|
||||||
|
|
||||||
|
event_dispatch();
|
||||||
|
|
||||||
|
bufferevent_free(bev);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
evhttp_free(http);
|
||||||
|
|
||||||
|
if (test_ok != 4) {
|
||||||
|
fprintf(stdout, "FAILED\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
http_suite(void)
|
http_suite(void)
|
||||||
{
|
{
|
||||||
@ -2146,6 +2203,8 @@ http_suite(void)
|
|||||||
http_highport_test();
|
http_highport_test();
|
||||||
http_dispatcher_test();
|
http_dispatcher_test();
|
||||||
|
|
||||||
|
http_multi_line_header_test();
|
||||||
|
|
||||||
http_incomplete_test(0 /* use_timeout */);
|
http_incomplete_test(0 /* use_timeout */);
|
||||||
http_incomplete_test(1 /* use_timeout */);
|
http_incomplete_test(1 /* use_timeout */);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user