HTTP keep-alive connections support.

This commit is contained in:
Igor Sysoev
2017-12-28 16:01:06 +03:00
parent 497faf1b9a
commit 9a6d3c5775
17 changed files with 2000 additions and 898 deletions

View File

@@ -10,6 +10,8 @@
#include <nxt_runtime.h>
#include <nxt_application.h>
#include <nxt_main_process.h>
#include <nxt_router.h>
#include <nxt_http.h>
#include <glob.h>
@@ -28,22 +30,8 @@ static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task,
const char *name);
static nxt_app_type_t nxt_app_parse_type(u_char *p, size_t length);
static nxt_int_t nxt_app_request_content_length(void *ctx,
nxt_http_field_t *field, uintptr_t data);
static nxt_int_t nxt_app_request_content_type(void *ctx,
nxt_http_field_t *field, uintptr_t data);
static nxt_int_t nxt_app_request_cookie(void *ctx, nxt_http_field_t *field,
uintptr_t data);
static nxt_int_t nxt_app_request_host(void *ctx, nxt_http_field_t *field,
uintptr_t data);
static nxt_http_field_proc_t nxt_app_request_fields[] = {
{ nxt_string("Content-Length"), &nxt_app_request_content_length, 0 },
{ nxt_string("Content-Type"), &nxt_app_request_content_type, 0 },
{ nxt_string("Cookie"), &nxt_app_request_cookie, 0 },
{ nxt_string("Host"), &nxt_app_request_host, 0 },
};
static void nxt_app_http_release(nxt_task_t *task, void *obj, void *data);
static uint32_t compat[] = {
@@ -51,8 +39,6 @@ static uint32_t compat[] = {
};
static nxt_lvlhsh_t nxt_app_request_fields_hash;
static nxt_thread_mutex_t nxt_app_mutex;
static nxt_thread_cond_t nxt_app_cond;
@@ -372,15 +358,6 @@ nxt_app_module_load(nxt_task_t *task, const char *name)
}
nxt_int_t
nxt_app_http_init(nxt_task_t *task, nxt_runtime_t *rt)
{
return nxt_http_fields_hash(&nxt_app_request_fields_hash, rt->mem_pool,
nxt_app_request_fields,
nxt_nitems(nxt_app_request_fields));
}
void
nxt_app_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
{
@@ -704,200 +681,32 @@ nxt_app_msg_read_size(nxt_task_t *task, nxt_app_rmsg_t *msg, size_t *size)
}
static nxt_int_t
nxt_app_request_content_length(void *ctx, nxt_http_field_t *field,
uintptr_t data)
{
nxt_app_parse_ctx_t *c;
nxt_app_request_header_t *h;
c = ctx;
h = &c->r.header;
h->content_length.length = field->value_length;
h->content_length.start = field->value;
h->parsed_content_length = nxt_off_t_parse(field->value,
field->value_length);
return NXT_OK;
}
static nxt_int_t
nxt_app_request_content_type(void *ctx, nxt_http_field_t *field,
uintptr_t data)
{
nxt_app_parse_ctx_t *c;
nxt_app_request_header_t *h;
c = ctx;
h = &c->r.header;
h->content_type.length = field->value_length;
h->content_type.start = field->value;
return NXT_OK;
}
static nxt_int_t
nxt_app_request_cookie(void *ctx, nxt_http_field_t *field, uintptr_t data)
{
nxt_app_parse_ctx_t *c;
nxt_app_request_header_t *h;
c = ctx;
h = &c->r.header;
h->cookie.length = field->value_length;
h->cookie.start = field->value;
return NXT_OK;
}
static nxt_int_t
nxt_app_request_host(void *ctx, nxt_http_field_t *field, uintptr_t data)
{
nxt_app_parse_ctx_t *c;
nxt_app_request_header_t *h;
c = ctx;
h = &c->r.header;
h->host.length = field->value_length;
h->host.start = field->value;
return NXT_OK;
}
nxt_app_parse_ctx_t *
nxt_app_http_req_init(nxt_task_t *task)
{
nxt_mp_t *mp;
nxt_int_t rc;
nxt_app_parse_ctx_t *ctx;
mp = nxt_mp_create(1024, 128, 256, 32);
if (nxt_slow_path(mp == NULL)) {
return NULL;
}
ctx = nxt_mp_zget(mp, sizeof(nxt_app_parse_ctx_t));
if (nxt_slow_path(ctx == NULL)) {
nxt_mp_destroy(mp);
return NULL;
}
ctx->mem_pool = mp;
rc = nxt_http_parse_request_init(&ctx->parser, mp);
if (nxt_slow_path(rc != NXT_OK)) {
nxt_mp_destroy(mp);
return NULL;
}
return ctx;
}
nxt_int_t
nxt_app_http_req_header_parse(nxt_task_t *task, nxt_app_parse_ctx_t *ctx,
nxt_buf_t *buf)
nxt_app_http_req_done(nxt_task_t *task, nxt_app_parse_ctx_t *ar)
{
nxt_int_t rc;
nxt_app_request_body_t *b;
nxt_http_request_parse_t *p;
nxt_app_request_header_t *h;
p = &ctx->parser;
b = &ctx->r.body;
h = &ctx->r.header;
nxt_assert(h->done == 0);
rc = nxt_http_parse_request(p, &buf->mem);
if (nxt_slow_path(rc != NXT_DONE)) {
return rc;
}
rc = nxt_http_fields_process(p->fields, &nxt_app_request_fields_hash, ctx);
if (nxt_slow_path(rc != NXT_OK)) {
return rc;
}
h->fields = p->fields;
h->done = 1;
h->version.start = p->version.str;
h->version.length = sizeof(p->version.str);
h->method = p->method;
h->target.start = p->target_start;
h->target.length = p->target_end - p->target_start;
h->path = p->path;
h->query = p->args;
if (h->parsed_content_length == 0) {
b->done = 1;
}
if (buf->mem.free == buf->mem.pos) {
return NXT_DONE;
}
b->buf = buf;
b->done = nxt_buf_mem_used_size(&buf->mem) >=
h->parsed_content_length;
if (b->done == 1) {
b->preread_size = nxt_buf_mem_used_size(&buf->mem);
}
return NXT_DONE;
}
nxt_int_t
nxt_app_http_req_body_read(nxt_task_t *task, nxt_app_parse_ctx_t *ctx,
nxt_buf_t *buf)
{
nxt_app_request_body_t *b;
nxt_app_request_header_t *h;
b = &ctx->r.body;
h = &ctx->r.header;
nxt_assert(h->done == 1);
nxt_assert(b->done == 0);
b->done = nxt_buf_mem_used_size(&buf->mem) + b->preread_size >=
(size_t) h->parsed_content_length;
if (b->done == 1) {
b->preread_size += nxt_buf_mem_used_size(&buf->mem);
}
return b->done == 1 ? NXT_DONE : NXT_AGAIN;
}
nxt_int_t
nxt_app_http_req_done(nxt_task_t *task, nxt_app_parse_ctx_t *ctx)
{
nxt_mp_release(ctx->mem_pool);
ar->timer.handler = nxt_app_http_release;
nxt_timer_add(task->thread->engine, &ar->timer, 0);
return NXT_OK;
}
static void
nxt_app_http_release(nxt_task_t *task, void *obj, void *data)
{
nxt_timer_t *timer;
nxt_app_parse_ctx_t *ar;
timer = obj;
nxt_debug(task, "http app release");
ar = nxt_timer_data(timer, nxt_app_parse_ctx_t, timer);
nxt_mp_release(ar->request->mem_pool);
}
nxt_int_t
nxt_app_msg_flush(nxt_task_t *task, nxt_app_wmsg_t *msg, nxt_bool_t last)
{