diff options
author | Igor Sysoev <igor@sysoev.ru> | 2018-04-10 19:38:45 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2018-04-10 19:38:45 +0300 |
commit | 73bdb5ec09b0f9ba65caf895b28c27e825c4b536 (patch) | |
tree | 667b86eca10a531a9f996ed2b1771ae3fd181de0 | |
parent | 0a44ac371aaac75d505f9158d3553481a69c2609 (diff) | |
download | unit-73bdb5ec09b0f9ba65caf895b28c27e825c4b536.tar.gz unit-73bdb5ec09b0f9ba65caf895b28c27e825c4b536.tar.bz2 |
Refactored HTTP header parsing.
-rw-r--r-- | src/nxt_h1proto.c | 94 |
1 files changed, 54 insertions, 40 deletions
diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index e22983d5..79d9802d 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -19,6 +19,8 @@ static void nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_conn_header_parse(nxt_task_t *task, void *obj, void *data); static nxt_int_t nxt_h1p_header_process(nxt_h1proto_t *h1p, nxt_http_request_t *r); +static nxt_int_t nxt_h1p_header_buffer_test(nxt_task_t *task, + nxt_h1proto_t *h1p, nxt_conn_t *c, nxt_socket_conf_t *skcf); static nxt_int_t nxt_h1p_connection(void *ctx, nxt_http_field_t *field, uintptr_t data); static nxt_int_t nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, @@ -302,9 +304,7 @@ static const nxt_conn_state_t nxt_h1p_header_parse_state static void nxt_h1p_conn_header_parse(nxt_task_t *task, void *obj, void *data) { - size_t size; nxt_int_t ret; - nxt_buf_t *in, *b; nxt_conn_t *c; nxt_h1proto_t *h1p; nxt_http_status_t status; @@ -319,7 +319,11 @@ nxt_h1p_conn_header_parse(nxt_task_t *task, void *obj, void *data) r = h1p->request; - if (nxt_fast_path(ret == NXT_DONE)) { + ret = nxt_expect(NXT_DONE, ret); + + switch (ret) { + + case NXT_DONE: /* * By default the keepalive mode is disabled in HTTP/1.0 and * enabled in HTTP/1.1. The mode can be overridden later by @@ -335,49 +339,21 @@ nxt_h1p_conn_header_parse(nxt_task_t *task, void *obj, void *data) } /* ret == NXT_ERROR */ + status = NXT_HTTP_BAD_REQUEST; - nxt_http_request_error(task, r, NXT_HTTP_BAD_REQUEST); - return; - } - - if (ret == NXT_AGAIN) { - in = c->read; - - if (nxt_buf_mem_free_size(&in->mem) == 0) { - size = r->socket_conf->large_header_buffer_size; - - if (size <= (size_t) nxt_buf_mem_used_size(&in->mem) - || h1p->nbuffers >= r->socket_conf->large_header_buffers) - { - (void) nxt_h1p_header_process(h1p, r); - nxt_http_request_error(task, r, - NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE); - return; - } - - b = nxt_buf_mem_alloc(c->mem_pool, size, 0); - if (nxt_slow_path(b == NULL)) { - (void) nxt_h1p_header_process(h1p, r); - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return; - } + goto error; - h1p->nbuffers++; + case NXT_AGAIN: + status = nxt_h1p_header_buffer_test(task, h1p, c, r->socket_conf); - size = nxt_buf_mem_used_size(&in->mem); - b->mem.free = nxt_cpymem(b->mem.pos, in->mem.pos, size); + if (nxt_fast_path(status == NXT_OK)) { + c->read_state = &nxt_h1p_header_parse_state; - in->next = h1p->buffers; - h1p->buffers = in; - c->read = b; + nxt_conn_read(task->thread->engine, c); + return; } - c->read_state = &nxt_h1p_header_parse_state; - nxt_conn_read(task->thread->engine, c); - return; - } - - switch (ret) { + break; case NXT_HTTP_PARSE_INVALID: status = NXT_HTTP_BAD_REQUEST; @@ -398,6 +374,9 @@ nxt_h1p_conn_header_parse(nxt_task_t *task, void *obj, void *data) } (void) nxt_h1p_header_process(h1p, r); + +error: + nxt_http_request_error(task, r, status); } @@ -424,6 +403,41 @@ nxt_h1p_header_process(nxt_h1proto_t *h1p, nxt_http_request_t *r) static nxt_int_t +nxt_h1p_header_buffer_test(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c, + nxt_socket_conf_t *skcf) +{ + size_t size, used; + nxt_buf_t *in, *b; + + in = c->read; + + if (nxt_buf_mem_free_size(&in->mem) == 0) { + size = skcf->large_header_buffer_size; + used = nxt_buf_mem_used_size(&in->mem); + + if (size <= used || h1p->nbuffers >= skcf->large_header_buffers) { + return NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; + } + + b = nxt_buf_mem_alloc(c->mem_pool, size, 0); + if (nxt_slow_path(b == NULL)) { + return NXT_HTTP_INTERNAL_SERVER_ERROR; + } + + b->mem.free = nxt_cpymem(b->mem.pos, in->mem.pos, used); + + in->next = h1p->buffers; + h1p->buffers = in; + h1p->nbuffers++; + + c->read = b; + } + + return NXT_OK; +} + + +static nxt_int_t nxt_h1p_connection(void *ctx, nxt_http_field_t *field, uintptr_t data) { nxt_http_request_t *r; |