Unit application library.
Library now used in all language modules. Old 'nxt_app_*' code removed. See src/test/nxt_unit_app_test.c for usage sample.
This commit is contained in:
781
src/nxt_router.c
781
src/nxt_router.c
@@ -8,6 +8,9 @@
|
||||
#include <nxt_router.h>
|
||||
#include <nxt_conf.h>
|
||||
#include <nxt_http.h>
|
||||
#include <nxt_port_memory_int.h>
|
||||
#include <nxt_unit_request.h>
|
||||
#include <nxt_unit_response.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
@@ -241,16 +244,8 @@ static nxt_int_t nxt_router_app_port(nxt_task_t *task, nxt_app_t *app,
|
||||
|
||||
static void nxt_router_app_prepare_request(nxt_task_t *task,
|
||||
nxt_req_app_link_t *ra);
|
||||
static nxt_int_t nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
|
||||
nxt_app_wmsg_t *wmsg);
|
||||
static nxt_int_t nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
|
||||
nxt_app_wmsg_t *wmsg);
|
||||
static nxt_int_t nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
|
||||
nxt_app_wmsg_t *wmsg);
|
||||
static nxt_int_t nxt_perl_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
|
||||
nxt_app_wmsg_t *wmsg);
|
||||
static nxt_int_t nxt_ruby_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
|
||||
nxt_app_wmsg_t *wmsg);
|
||||
static nxt_buf_t *nxt_router_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
|
||||
nxt_port_t *port, const nxt_str_t *prefix);
|
||||
|
||||
static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data);
|
||||
static void nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj,
|
||||
@@ -265,13 +260,15 @@ static void nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data);
|
||||
|
||||
static nxt_router_t *nxt_router;
|
||||
|
||||
static const nxt_str_t http_prefix = nxt_string("HTTP_");
|
||||
static const nxt_str_t empty_prefix = nxt_string("");
|
||||
|
||||
static nxt_app_prepare_msg_t nxt_app_prepare_msg[] = {
|
||||
nxt_python_prepare_msg,
|
||||
nxt_php_prepare_msg,
|
||||
nxt_go_prepare_msg,
|
||||
nxt_perl_prepare_msg,
|
||||
nxt_ruby_prepare_msg,
|
||||
static const nxt_str_t *nxt_app_msg_prefix[] = {
|
||||
&http_prefix,
|
||||
&http_prefix,
|
||||
&empty_prefix,
|
||||
&http_prefix,
|
||||
&http_prefix,
|
||||
};
|
||||
|
||||
|
||||
@@ -1459,7 +1456,6 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
||||
app->live = 1;
|
||||
app->max_pending_responses = 2;
|
||||
app->max_requests = apcf.requests;
|
||||
app->prepare_msg = nxt_app_prepare_msg[lang->type];
|
||||
|
||||
engine = task->thread->engine;
|
||||
|
||||
@@ -3145,6 +3141,7 @@ nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
|
||||
nxt_http_request_t *r;
|
||||
nxt_req_conn_link_t *rc;
|
||||
nxt_app_parse_ctx_t *ar;
|
||||
nxt_unit_response_t *resp;
|
||||
|
||||
b = msg->buf;
|
||||
rc = data;
|
||||
@@ -3204,11 +3201,48 @@ nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
|
||||
nxt_http_request_send_body(task, r, NULL);
|
||||
|
||||
} else {
|
||||
size_t b_size = nxt_buf_mem_used_size(&b->mem);
|
||||
|
||||
if (nxt_slow_path(b_size < sizeof(*resp))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
resp = (void *) b->mem.pos;
|
||||
if (nxt_slow_path(b_size < sizeof(*resp)
|
||||
+ resp->fields_count * sizeof(nxt_unit_field_t))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nxt_unit_field_t *f;
|
||||
nxt_http_field_t *field;
|
||||
|
||||
for (f = resp->fields; f < resp->fields + resp->fields_count; f++) {
|
||||
field = nxt_list_add(ar->resp_parser.fields);
|
||||
|
||||
if (nxt_slow_path(field == NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
field->hash = f->hash;
|
||||
field->skip = f->skip;
|
||||
|
||||
field->name_length = f->name_length;
|
||||
field->value_length = f->value_length;
|
||||
field->name = nxt_unit_sptr_get(&f->name);
|
||||
field->value = nxt_unit_sptr_get(&f->value);
|
||||
|
||||
nxt_debug(task, "header: %*s: %*s",
|
||||
(size_t) field->name_length, field->name,
|
||||
(size_t) field->value_length, field->value);
|
||||
}
|
||||
r->status = resp->status;
|
||||
|
||||
/*
|
||||
ret = nxt_http_parse_fields(&ar->resp_parser, &b->mem);
|
||||
if (nxt_slow_path(ret != NXT_DONE)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*/
|
||||
r->resp.fields = ar->resp_parser.fields;
|
||||
|
||||
ret = nxt_http_fields_process(r->resp.fields,
|
||||
@@ -3217,6 +3251,14 @@ nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (resp->piggyback_content_length != 0) {
|
||||
b->mem.pos = nxt_unit_sptr_get(&resp->piggyback_content);
|
||||
b->mem.free = b->mem.pos + resp->piggyback_content_length;
|
||||
|
||||
} else {
|
||||
b->mem.pos = b->mem.free;
|
||||
}
|
||||
|
||||
if (nxt_buf_mem_used_size(&b->mem) == 0) {
|
||||
nxt_work_queue_add(&task->thread->engine->fast_work_queue,
|
||||
b->completion_handler, task, b, b->parent);
|
||||
@@ -4208,10 +4250,9 @@ static void
|
||||
nxt_router_app_prepare_request(nxt_task_t *task, nxt_req_app_link_t *ra)
|
||||
{
|
||||
uint32_t request_failed;
|
||||
nxt_buf_t *b;
|
||||
nxt_buf_t *buf;
|
||||
nxt_int_t res;
|
||||
nxt_port_t *port, *c_port, *reply_port;
|
||||
nxt_app_wmsg_t wmsg;
|
||||
nxt_app_parse_ctx_t *ap;
|
||||
|
||||
nxt_assert(ra->app_port != NULL);
|
||||
@@ -4236,32 +4277,30 @@ nxt_router_app_prepare_request(nxt_task_t *task, nxt_req_app_link_t *ra)
|
||||
nxt_process_connected_port_add(port->process, reply_port);
|
||||
}
|
||||
|
||||
wmsg.port = port;
|
||||
wmsg.write = NULL;
|
||||
wmsg.buf = &wmsg.write;
|
||||
wmsg.stream = ra->stream;
|
||||
buf = nxt_router_prepare_msg(task, &ap->r, port,
|
||||
nxt_app_msg_prefix[port->app->type]);
|
||||
|
||||
res = port->app->prepare_msg(task, &ap->r, &wmsg);
|
||||
|
||||
if (nxt_slow_path(res != NXT_OK)) {
|
||||
if (nxt_slow_path(buf == NULL)) {
|
||||
nxt_router_ra_error(ra, 500,
|
||||
"Failed to prepare message for application");
|
||||
goto release_port;
|
||||
}
|
||||
|
||||
nxt_debug(task, "about to send %O bytes buffer to app process port %d",
|
||||
nxt_buf_used_size(wmsg.write),
|
||||
wmsg.port->socket.fd);
|
||||
nxt_buf_used_size(buf),
|
||||
port->socket.fd);
|
||||
|
||||
request_failed = 0;
|
||||
|
||||
ra->msg_info.buf = wmsg.write;
|
||||
ra->msg_info.completion_handler = wmsg.write->completion_handler;
|
||||
ra->msg_info.buf = buf;
|
||||
ra->msg_info.completion_handler = buf->completion_handler;
|
||||
|
||||
for (b = wmsg.write; b != NULL; b = b->next) {
|
||||
b->completion_handler = nxt_router_dummy_buf_completion;
|
||||
for (; buf; buf = buf->next) {
|
||||
buf->completion_handler = nxt_router_dummy_buf_completion;
|
||||
}
|
||||
|
||||
buf = ra->msg_info.buf;
|
||||
|
||||
res = nxt_port_mmap_get_tracking(task, port, &ra->msg_info.tracking,
|
||||
ra->stream);
|
||||
if (nxt_slow_path(res != NXT_OK)) {
|
||||
@@ -4270,8 +4309,8 @@ nxt_router_app_prepare_request(nxt_task_t *task, nxt_req_app_link_t *ra)
|
||||
goto release_port;
|
||||
}
|
||||
|
||||
res = nxt_port_socket_twrite(task, wmsg.port, NXT_PORT_MSG_DATA,
|
||||
-1, ra->stream, reply_port->id, wmsg.write,
|
||||
res = nxt_port_socket_twrite(task, port, NXT_PORT_MSG_DATA,
|
||||
-1, ra->stream, reply_port->id, buf,
|
||||
&ra->msg_info.tracking);
|
||||
|
||||
if (nxt_slow_path(res != NXT_OK)) {
|
||||
@@ -4288,421 +4327,317 @@ release_port:
|
||||
}
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
|
||||
nxt_app_wmsg_t *wmsg)
|
||||
{
|
||||
nxt_int_t rc;
|
||||
nxt_buf_t *b;
|
||||
nxt_http_field_t *field;
|
||||
nxt_app_request_header_t *h;
|
||||
struct nxt_fields_iter_s {
|
||||
nxt_list_part_t *part;
|
||||
nxt_http_field_t *field;
|
||||
};
|
||||
|
||||
static const nxt_str_t prefix = nxt_string("HTTP_");
|
||||
static const nxt_str_t eof = nxt_null_string;
|
||||
typedef struct nxt_fields_iter_s nxt_fields_iter_t;
|
||||
|
||||
|
||||
static nxt_http_field_t *
|
||||
nxt_fields_part_first(nxt_list_part_t *part, nxt_fields_iter_t *i)
|
||||
{
|
||||
if (part == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (part->nelts == 0) {
|
||||
part = part->next;
|
||||
if (part == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
i->part = part;
|
||||
i->field = nxt_list_data(i->part);
|
||||
|
||||
return i->field;
|
||||
}
|
||||
|
||||
|
||||
static nxt_http_field_t *
|
||||
nxt_fields_first(nxt_list_t *fields, nxt_fields_iter_t *i)
|
||||
{
|
||||
return nxt_fields_part_first(nxt_list_part(fields), i);
|
||||
}
|
||||
|
||||
|
||||
static nxt_http_field_t *
|
||||
nxt_fields_next(nxt_fields_iter_t *i)
|
||||
{
|
||||
nxt_http_field_t *end = nxt_list_data(i->part);
|
||||
|
||||
end += i->part->nelts;
|
||||
i->field++;
|
||||
|
||||
if (i->field < end) {
|
||||
return i->field;
|
||||
}
|
||||
|
||||
return nxt_fields_part_first(i->part->next, i);
|
||||
}
|
||||
|
||||
|
||||
static nxt_buf_t *
|
||||
nxt_router_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
|
||||
nxt_port_t *port, const nxt_str_t *prefix)
|
||||
{
|
||||
void *target_pos, *query_pos;
|
||||
u_char *pos, *end, *p, c;
|
||||
size_t fields_count, req_size, size, free_size;
|
||||
size_t copy_size;
|
||||
nxt_buf_t *b, *buf, *out, **tail;
|
||||
nxt_http_field_t *field, *dup;
|
||||
nxt_unit_field_t *dst_field;
|
||||
nxt_fields_iter_t iter, dup_iter;
|
||||
nxt_unit_request_t *req;
|
||||
nxt_app_request_header_t *h;
|
||||
|
||||
h = &r->header;
|
||||
|
||||
#define RC(S) \
|
||||
do { \
|
||||
rc = (S); \
|
||||
if (nxt_slow_path(rc != NXT_OK)) { \
|
||||
goto fail; \
|
||||
} \
|
||||
} while(0)
|
||||
req_size = sizeof(nxt_unit_request_t)
|
||||
+ h->method.length + 1
|
||||
+ h->version.length + 1
|
||||
+ r->remote.length + 1
|
||||
+ r->local.length + 1
|
||||
+ h->target.length + 1
|
||||
+ (h->path.start != h->target.start ? h->path.length + 1 : 0);
|
||||
|
||||
#define NXT_WRITE(N) \
|
||||
RC(nxt_app_msg_write_str(task, wmsg, N))
|
||||
fields_count = 0;
|
||||
|
||||
/* TODO error handle, async mmap buffer assignment */
|
||||
nxt_list_each(field, h->fields) {
|
||||
fields_count++;
|
||||
|
||||
NXT_WRITE(&h->method);
|
||||
NXT_WRITE(&h->target);
|
||||
req_size += field->name_length + prefix->length + 1
|
||||
+ field->value_length + 1;
|
||||
} nxt_list_loop;
|
||||
|
||||
req_size += fields_count * sizeof(nxt_unit_field_t);
|
||||
|
||||
if (nxt_slow_path(req_size > PORT_MMAP_DATA_SIZE)) {
|
||||
nxt_alert(task, "headers to big to fit in shared memory (%d)",
|
||||
(int) req_size);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out = nxt_port_mmap_get_buf(task, port,
|
||||
nxt_min(req_size + r->body.preread_size, PORT_MMAP_DATA_SIZE));
|
||||
if (nxt_slow_path(out == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
req = (nxt_unit_request_t *) out->mem.free;
|
||||
out->mem.free += req_size;
|
||||
|
||||
req->content_length = h->parsed_content_length;
|
||||
|
||||
p = (u_char *) (req->fields + fields_count);
|
||||
|
||||
nxt_debug(task, "fields_count=%d", (int) fields_count);
|
||||
|
||||
req->method_length = h->method.length;
|
||||
nxt_unit_sptr_set(&req->method, p);
|
||||
p = nxt_cpymem(p, h->method.start, h->method.length);
|
||||
*p++ = '\0';
|
||||
|
||||
req->version_length = h->version.length;
|
||||
nxt_unit_sptr_set(&req->version, p);
|
||||
p = nxt_cpymem(p, h->version.start, h->version.length);
|
||||
*p++ = '\0';
|
||||
|
||||
req->remote_length = r->remote.length;
|
||||
nxt_unit_sptr_set(&req->remote, p);
|
||||
p = nxt_cpymem(p, r->remote.start, r->remote.length);
|
||||
*p++ = '\0';
|
||||
|
||||
req->local_length = r->local.length;
|
||||
nxt_unit_sptr_set(&req->local, p);
|
||||
p = nxt_cpymem(p, r->local.start, r->local.length);
|
||||
*p++ = '\0';
|
||||
|
||||
target_pos = p;
|
||||
req->target_length = h->target.length;
|
||||
nxt_unit_sptr_set(&req->target, p);
|
||||
p = nxt_cpymem(p, h->target.start, h->target.length);
|
||||
*p++ = '\0';
|
||||
|
||||
req->path_length = h->path.length;
|
||||
if (h->path.start == h->target.start) {
|
||||
NXT_WRITE(&eof);
|
||||
nxt_unit_sptr_set(&req->path, target_pos);
|
||||
|
||||
} else {
|
||||
NXT_WRITE(&h->path);
|
||||
nxt_unit_sptr_set(&req->path, p);
|
||||
p = nxt_cpymem(p, h->path.start, h->path.length);
|
||||
*p++ = '\0';
|
||||
}
|
||||
|
||||
req->query_length = h->query.length;
|
||||
if (h->query.start != NULL) {
|
||||
RC(nxt_app_msg_write_size(task, wmsg,
|
||||
h->query.start - h->target.start + 1));
|
||||
query_pos = nxt_pointer_to(target_pos,
|
||||
h->query.start - h->target.start);
|
||||
|
||||
nxt_unit_sptr_set(&req->query, query_pos);
|
||||
|
||||
} else {
|
||||
RC(nxt_app_msg_write_size(task, wmsg, 0));
|
||||
req->query.offset = 0;
|
||||
}
|
||||
|
||||
NXT_WRITE(&h->version);
|
||||
req->host_field = NXT_UNIT_NONE_FIELD;
|
||||
req->content_length_field = NXT_UNIT_NONE_FIELD;
|
||||
req->content_type_field = NXT_UNIT_NONE_FIELD;
|
||||
req->cookie_field = NXT_UNIT_NONE_FIELD;
|
||||
|
||||
NXT_WRITE(&r->remote);
|
||||
NXT_WRITE(&r->local);
|
||||
dst_field = req->fields;
|
||||
|
||||
NXT_WRITE(&h->host);
|
||||
NXT_WRITE(&h->content_type);
|
||||
NXT_WRITE(&h->content_length);
|
||||
for (field = nxt_fields_first(h->fields, &iter);
|
||||
field != NULL;
|
||||
field = nxt_fields_next(&iter))
|
||||
{
|
||||
if (field->skip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nxt_list_each(field, h->fields) {
|
||||
RC(nxt_app_msg_write_prefixed_upcase(task, wmsg, &prefix, field->name,
|
||||
field->name_length));
|
||||
RC(nxt_app_msg_write(task, wmsg, field->value, field->value_length));
|
||||
dst_field->hash = field->hash;
|
||||
dst_field->skip = 0;
|
||||
dst_field->name_length = field->name_length + prefix->length;
|
||||
dst_field->value_length = field->value_length;
|
||||
|
||||
} nxt_list_loop;
|
||||
if (field->value == h->host.start) {
|
||||
req->host_field = dst_field - req->fields;
|
||||
|
||||
/* end-of-headers mark */
|
||||
NXT_WRITE(&eof);
|
||||
} else if (field->value == h->content_length.start) {
|
||||
req->content_length_field = dst_field - req->fields;
|
||||
|
||||
RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size));
|
||||
} else if (field->value == h->content_type.start) {
|
||||
req->content_type_field = dst_field - req->fields;
|
||||
|
||||
} else if (field->value == h->cookie.start) {
|
||||
req->cookie_field = dst_field - req->fields;
|
||||
}
|
||||
|
||||
nxt_debug(task, "add field 0x%04Xd, %d, %d, %p : %d %p",
|
||||
(int) field->hash, (int) field->skip,
|
||||
(int) field->name_length, field->name,
|
||||
(int) field->value_length, field->value);
|
||||
|
||||
if (prefix->length != 0) {
|
||||
nxt_unit_sptr_set(&dst_field->name, p);
|
||||
p = nxt_cpymem(p, prefix->start, prefix->length);
|
||||
|
||||
end = field->name + field->name_length;
|
||||
for (pos = field->name; pos < end; pos++) {
|
||||
c = *pos;
|
||||
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
*p++ = (c & ~0x20);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '-') {
|
||||
*p++ = '_';
|
||||
continue;
|
||||
}
|
||||
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
} else {
|
||||
nxt_unit_sptr_set(&dst_field->name, p);
|
||||
p = nxt_cpymem(p, field->name, field->name_length);
|
||||
}
|
||||
|
||||
*p++ = '\0';
|
||||
|
||||
nxt_unit_sptr_set(&dst_field->value, p);
|
||||
p = nxt_cpymem(p, field->value, field->value_length);
|
||||
|
||||
if (prefix->length != 0) {
|
||||
dup_iter = iter;
|
||||
|
||||
for (dup = nxt_fields_next(&dup_iter);
|
||||
dup != NULL;
|
||||
dup = nxt_fields_next(&dup_iter))
|
||||
{
|
||||
if (dup->name_length != field->name_length
|
||||
|| dup->skip
|
||||
|| dup->hash != field->hash
|
||||
|| nxt_memcasecmp(dup->name, field->name, dup->name_length))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
p = nxt_cpymem(p, ", ", 2);
|
||||
p = nxt_cpymem(p, dup->value, dup->value_length);
|
||||
|
||||
dst_field->value_length += 2 + dup->value_length;
|
||||
|
||||
dup->skip = 1;
|
||||
}
|
||||
}
|
||||
|
||||
*p++ = '\0';
|
||||
|
||||
dst_field++;
|
||||
}
|
||||
|
||||
req->fields_count = dst_field - req->fields;
|
||||
|
||||
nxt_unit_sptr_set(&req->preread_content, out->mem.free);
|
||||
|
||||
buf = out;
|
||||
tail = &buf->next;
|
||||
|
||||
for (b = r->body.buf; b != NULL; b = b->next) {
|
||||
RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos,
|
||||
nxt_buf_mem_used_size(&b->mem)));
|
||||
size = nxt_buf_mem_used_size(&b->mem);
|
||||
pos = b->mem.pos;
|
||||
|
||||
while (size > 0) {
|
||||
if (buf == NULL) {
|
||||
free_size = nxt_min(size, PORT_MMAP_DATA_SIZE);
|
||||
|
||||
buf = nxt_port_mmap_get_buf(task, port, free_size);
|
||||
if (nxt_slow_path(buf == NULL)) {
|
||||
while (out != NULL) {
|
||||
buf = out->next;
|
||||
out->completion_handler(task, out, out->parent);
|
||||
out = buf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*tail = buf;
|
||||
tail = &buf->next;
|
||||
|
||||
} else {
|
||||
free_size = nxt_buf_mem_free_size(&buf->mem);
|
||||
if (free_size < size
|
||||
&& nxt_port_mmap_increase_buf(task, buf, size, 1)
|
||||
== NXT_OK)
|
||||
{
|
||||
free_size = nxt_buf_mem_free_size(&buf->mem);
|
||||
}
|
||||
}
|
||||
|
||||
if (free_size > 0) {
|
||||
copy_size = nxt_min(free_size, size);
|
||||
|
||||
buf->mem.free = nxt_cpymem(buf->mem.free, pos, copy_size);
|
||||
|
||||
size -= copy_size;
|
||||
pos += copy_size;
|
||||
|
||||
if (size == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#undef NXT_WRITE
|
||||
#undef RC
|
||||
|
||||
return NXT_OK;
|
||||
|
||||
fail:
|
||||
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
|
||||
nxt_app_wmsg_t *wmsg)
|
||||
{
|
||||
nxt_int_t rc;
|
||||
nxt_buf_t *b;
|
||||
nxt_http_field_t *field;
|
||||
nxt_app_request_header_t *h;
|
||||
|
||||
static const nxt_str_t prefix = nxt_string("HTTP_");
|
||||
static const nxt_str_t eof = nxt_null_string;
|
||||
|
||||
h = &r->header;
|
||||
|
||||
#define RC(S) \
|
||||
do { \
|
||||
rc = (S); \
|
||||
if (nxt_slow_path(rc != NXT_OK)) { \
|
||||
goto fail; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define NXT_WRITE(N) \
|
||||
RC(nxt_app_msg_write_str(task, wmsg, N))
|
||||
|
||||
/* TODO error handle, async mmap buffer assignment */
|
||||
|
||||
NXT_WRITE(&h->method);
|
||||
NXT_WRITE(&h->target);
|
||||
|
||||
if (h->path.start == h->target.start) {
|
||||
NXT_WRITE(&eof);
|
||||
|
||||
} else {
|
||||
NXT_WRITE(&h->path);
|
||||
}
|
||||
|
||||
if (h->query.start != NULL) {
|
||||
RC(nxt_app_msg_write_size(task, wmsg,
|
||||
h->query.start - h->target.start + 1));
|
||||
} else {
|
||||
RC(nxt_app_msg_write_size(task, wmsg, 0));
|
||||
}
|
||||
|
||||
NXT_WRITE(&h->version);
|
||||
|
||||
// PHP_SELF
|
||||
// SCRIPT_NAME
|
||||
// SCRIPT_FILENAME
|
||||
// DOCUMENT_ROOT
|
||||
|
||||
NXT_WRITE(&r->remote);
|
||||
NXT_WRITE(&r->local);
|
||||
|
||||
NXT_WRITE(&h->host);
|
||||
NXT_WRITE(&h->cookie);
|
||||
NXT_WRITE(&h->content_type);
|
||||
NXT_WRITE(&h->content_length);
|
||||
|
||||
RC(nxt_app_msg_write_size(task, wmsg, h->parsed_content_length));
|
||||
RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size));
|
||||
|
||||
for (b = r->body.buf; b != NULL; b = b->next) {
|
||||
RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos,
|
||||
nxt_buf_mem_used_size(&b->mem)));
|
||||
}
|
||||
|
||||
nxt_list_each(field, h->fields) {
|
||||
RC(nxt_app_msg_write_prefixed_upcase(task, wmsg, &prefix, field->name,
|
||||
field->name_length));
|
||||
RC(nxt_app_msg_write(task, wmsg, field->value, field->value_length));
|
||||
|
||||
} nxt_list_loop;
|
||||
|
||||
/* end-of-headers mark */
|
||||
NXT_WRITE(&eof);
|
||||
|
||||
#undef NXT_WRITE
|
||||
#undef RC
|
||||
|
||||
return NXT_OK;
|
||||
|
||||
fail:
|
||||
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, nxt_app_wmsg_t *wmsg)
|
||||
{
|
||||
nxt_int_t rc;
|
||||
nxt_buf_t *b;
|
||||
nxt_http_field_t *field;
|
||||
nxt_app_request_header_t *h;
|
||||
|
||||
static const nxt_str_t eof = nxt_null_string;
|
||||
|
||||
h = &r->header;
|
||||
|
||||
#define RC(S) \
|
||||
do { \
|
||||
rc = (S); \
|
||||
if (nxt_slow_path(rc != NXT_OK)) { \
|
||||
goto fail; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define NXT_WRITE(N) \
|
||||
RC(nxt_app_msg_write_str(task, wmsg, N))
|
||||
|
||||
/* TODO error handle, async mmap buffer assignment */
|
||||
|
||||
NXT_WRITE(&h->method);
|
||||
NXT_WRITE(&h->target);
|
||||
|
||||
if (h->path.start == h->target.start) {
|
||||
NXT_WRITE(&eof);
|
||||
|
||||
} else {
|
||||
NXT_WRITE(&h->path);
|
||||
}
|
||||
|
||||
if (h->query.start != NULL) {
|
||||
RC(nxt_app_msg_write_size(task, wmsg,
|
||||
h->query.start - h->target.start + 1));
|
||||
} else {
|
||||
RC(nxt_app_msg_write_size(task, wmsg, 0));
|
||||
}
|
||||
|
||||
NXT_WRITE(&h->version);
|
||||
NXT_WRITE(&r->remote);
|
||||
|
||||
NXT_WRITE(&h->host);
|
||||
NXT_WRITE(&h->cookie);
|
||||
NXT_WRITE(&h->content_type);
|
||||
NXT_WRITE(&h->content_length);
|
||||
|
||||
RC(nxt_app_msg_write_size(task, wmsg, h->parsed_content_length));
|
||||
|
||||
nxt_list_each(field, h->fields) {
|
||||
RC(nxt_app_msg_write(task, wmsg, field->name, field->name_length));
|
||||
RC(nxt_app_msg_write(task, wmsg, field->value, field->value_length));
|
||||
|
||||
} nxt_list_loop;
|
||||
|
||||
/* end-of-headers mark */
|
||||
NXT_WRITE(&eof);
|
||||
|
||||
RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size));
|
||||
|
||||
for (b = r->body.buf; b != NULL; b = b->next) {
|
||||
RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos,
|
||||
nxt_buf_mem_used_size(&b->mem)));
|
||||
}
|
||||
|
||||
#undef NXT_WRITE
|
||||
#undef RC
|
||||
|
||||
return NXT_OK;
|
||||
|
||||
fail:
|
||||
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_perl_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
|
||||
nxt_app_wmsg_t *wmsg)
|
||||
{
|
||||
nxt_int_t rc;
|
||||
nxt_str_t str;
|
||||
nxt_buf_t *b;
|
||||
nxt_http_field_t *field;
|
||||
nxt_app_request_header_t *h;
|
||||
|
||||
static const nxt_str_t prefix = nxt_string("HTTP_");
|
||||
static const nxt_str_t eof = nxt_null_string;
|
||||
|
||||
h = &r->header;
|
||||
|
||||
#define RC(S) \
|
||||
do { \
|
||||
rc = (S); \
|
||||
if (nxt_slow_path(rc != NXT_OK)) { \
|
||||
goto fail; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define NXT_WRITE(N) \
|
||||
RC(nxt_app_msg_write_str(task, wmsg, N))
|
||||
|
||||
/* TODO error handle, async mmap buffer assignment */
|
||||
|
||||
NXT_WRITE(&h->method);
|
||||
NXT_WRITE(&h->target);
|
||||
|
||||
if (h->query.length) {
|
||||
str.start = h->target.start;
|
||||
str.length = (h->target.length - h->query.length) - 1;
|
||||
|
||||
RC(nxt_app_msg_write_str(task, wmsg, &str));
|
||||
|
||||
} else {
|
||||
NXT_WRITE(&eof);
|
||||
}
|
||||
|
||||
if (h->query.start != NULL) {
|
||||
RC(nxt_app_msg_write_size(task, wmsg,
|
||||
h->query.start - h->target.start + 1));
|
||||
} else {
|
||||
RC(nxt_app_msg_write_size(task, wmsg, 0));
|
||||
}
|
||||
|
||||
NXT_WRITE(&h->version);
|
||||
|
||||
NXT_WRITE(&r->remote);
|
||||
NXT_WRITE(&r->local);
|
||||
|
||||
NXT_WRITE(&h->host);
|
||||
NXT_WRITE(&h->content_type);
|
||||
NXT_WRITE(&h->content_length);
|
||||
|
||||
nxt_list_each(field, h->fields) {
|
||||
RC(nxt_app_msg_write_prefixed_upcase(task, wmsg, &prefix,
|
||||
field->name, field->name_length));
|
||||
RC(nxt_app_msg_write(task, wmsg, field->value, field->value_length));
|
||||
} nxt_list_loop;
|
||||
|
||||
/* end-of-headers mark */
|
||||
NXT_WRITE(&eof);
|
||||
|
||||
RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size));
|
||||
|
||||
for (b = r->body.buf; b != NULL; b = b->next) {
|
||||
|
||||
RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos,
|
||||
nxt_buf_mem_used_size(&b->mem)));
|
||||
}
|
||||
|
||||
#undef NXT_WRITE
|
||||
#undef RC
|
||||
|
||||
return NXT_OK;
|
||||
|
||||
fail:
|
||||
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_ruby_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
|
||||
nxt_app_wmsg_t *wmsg)
|
||||
{
|
||||
nxt_int_t rc;
|
||||
nxt_str_t str;
|
||||
nxt_buf_t *b;
|
||||
nxt_http_field_t *field;
|
||||
nxt_app_request_header_t *h;
|
||||
|
||||
static const nxt_str_t prefix = nxt_string("HTTP_");
|
||||
static const nxt_str_t eof = nxt_null_string;
|
||||
|
||||
h = &r->header;
|
||||
|
||||
#define RC(S) \
|
||||
do { \
|
||||
rc = (S); \
|
||||
if (nxt_slow_path(rc != NXT_OK)) { \
|
||||
goto fail; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define NXT_WRITE(N) \
|
||||
RC(nxt_app_msg_write_str(task, wmsg, N))
|
||||
|
||||
/* TODO error handle, async mmap buffer assignment */
|
||||
|
||||
NXT_WRITE(&h->method);
|
||||
NXT_WRITE(&h->target);
|
||||
|
||||
if (h->query.length) {
|
||||
str.start = h->target.start;
|
||||
str.length = (h->target.length - h->query.length) - 1;
|
||||
|
||||
RC(nxt_app_msg_write_str(task, wmsg, &str));
|
||||
|
||||
} else {
|
||||
NXT_WRITE(&eof);
|
||||
}
|
||||
|
||||
if (h->query.start != NULL) {
|
||||
RC(nxt_app_msg_write_size(task, wmsg,
|
||||
h->query.start - h->target.start + 1));
|
||||
} else {
|
||||
RC(nxt_app_msg_write_size(task, wmsg, 0));
|
||||
}
|
||||
|
||||
NXT_WRITE(&h->version);
|
||||
|
||||
NXT_WRITE(&r->remote);
|
||||
NXT_WRITE(&r->local);
|
||||
|
||||
NXT_WRITE(&h->host);
|
||||
NXT_WRITE(&h->content_type);
|
||||
NXT_WRITE(&h->content_length);
|
||||
|
||||
nxt_list_each(field, h->fields) {
|
||||
RC(nxt_app_msg_write_prefixed_upcase(task, wmsg, &prefix,
|
||||
field->name, field->name_length));
|
||||
RC(nxt_app_msg_write(task, wmsg, field->value, field->value_length));
|
||||
} nxt_list_loop;
|
||||
|
||||
/* end-of-headers mark */
|
||||
NXT_WRITE(&eof);
|
||||
|
||||
RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size));
|
||||
|
||||
for (b = r->body.buf; b != NULL; b = b->next) {
|
||||
|
||||
RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos,
|
||||
nxt_buf_mem_used_size(&b->mem)));
|
||||
}
|
||||
|
||||
#undef NXT_WRITE
|
||||
#undef RC
|
||||
|
||||
return NXT_OK;
|
||||
|
||||
fail:
|
||||
|
||||
return NXT_ERROR;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user