summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_h1proto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nxt_h1proto.c')
-rw-r--r--src/nxt_h1proto.c94
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;