Python: changed request headers format in router protocol.

The coming ASGI support requires raw HTTP headers format.  Headers grouping
and upcase code were moved to WSGI module.
This commit is contained in:
Max Romanov
2020-09-15 20:12:25 +03:00
parent 5163551ffe
commit d5973fb557
2 changed files with 108 additions and 12 deletions

View File

@@ -259,7 +259,7 @@ static const nxt_str_t empty_prefix = nxt_string("");
static const nxt_str_t *nxt_app_msg_prefix[] = { static const nxt_str_t *nxt_app_msg_prefix[] = {
&empty_prefix, &empty_prefix,
&http_prefix, &empty_prefix,
&http_prefix, &http_prefix,
&http_prefix, &http_prefix,
&http_prefix, &http_prefix,

View File

@@ -43,6 +43,7 @@
#define PyString_FromStringAndSize(str, size) \ #define PyString_FromStringAndSize(str, size) \
PyUnicode_DecodeLatin1((str), (size), "strict") PyUnicode_DecodeLatin1((str), (size), "strict")
#define PyString_AS_STRING PyUnicode_DATA
#else #else
#define NXT_PYTHON_BYTES_TYPE "string" #define NXT_PYTHON_BYTES_TYPE "string"
@@ -73,7 +74,10 @@ static PyObject *nxt_python_get_environ(nxt_python_run_ctx_t *ctx);
static int nxt_python_add_sptr(nxt_python_run_ctx_t *ctx, PyObject *name, static int nxt_python_add_sptr(nxt_python_run_ctx_t *ctx, PyObject *name,
nxt_unit_sptr_t *sptr, uint32_t size); nxt_unit_sptr_t *sptr, uint32_t size);
static int nxt_python_add_field(nxt_python_run_ctx_t *ctx, static int nxt_python_add_field(nxt_python_run_ctx_t *ctx,
nxt_unit_field_t *field); nxt_unit_field_t *field, int n, uint32_t vl);
static PyObject *nxt_python_field_name(const char *name, uint8_t len);
static PyObject *nxt_python_field_value(nxt_unit_field_t *f, int n,
uint32_t vl);
static int nxt_python_add_obj(nxt_python_run_ctx_t *ctx, PyObject *name, static int nxt_python_add_obj(nxt_python_run_ctx_t *ctx, PyObject *name,
PyObject *value); PyObject *value);
@@ -511,9 +515,9 @@ static PyObject *
nxt_python_get_environ(nxt_python_run_ctx_t *ctx) nxt_python_get_environ(nxt_python_run_ctx_t *ctx)
{ {
int rc; int rc;
uint32_t i; uint32_t i, j, vl;
PyObject *environ; PyObject *environ;
nxt_unit_field_t *f; nxt_unit_field_t *f, *f2;
nxt_unit_request_t *r; nxt_unit_request_t *r;
environ = PyDict_Copy(nxt_py_environ_ptyp); environ = PyDict_Copy(nxt_py_environ_ptyp);
@@ -565,10 +569,27 @@ nxt_python_get_environ(nxt_python_run_ctx_t *ctx)
r->server_name_length)); r->server_name_length));
RC(nxt_python_add_obj(ctx, nxt_py_server_port_str, nxt_py_80_str)); RC(nxt_python_add_obj(ctx, nxt_py_server_port_str, nxt_py_80_str));
for (i = 0; i < r->fields_count; i++) { nxt_unit_request_group_dup_fields(ctx->req);
f = r->fields + i;
RC(nxt_python_add_field(ctx, f)); for (i = 0; i < r->fields_count;) {
f = r->fields + i;
vl = f->value_length;
for (j = i + 1; j < r->fields_count; j++) {
f2 = r->fields + j;
if (f2->hash != f->hash
|| nxt_unit_sptr_get(&f2->name) != nxt_unit_sptr_get(&f->name))
{
break;
}
vl += 2 + f2->value_length;
}
RC(nxt_python_add_field(ctx, f, j - i, vl));
i = j;
} }
if (r->content_length_field != NXT_UNIT_NONE_FIELD) { if (r->content_length_field != NXT_UNIT_NONE_FIELD) {
@@ -632,14 +653,15 @@ nxt_python_add_sptr(nxt_python_run_ctx_t *ctx, PyObject *name,
static int static int
nxt_python_add_field(nxt_python_run_ctx_t *ctx, nxt_unit_field_t *field) nxt_python_add_field(nxt_python_run_ctx_t *ctx, nxt_unit_field_t *field, int n,
uint32_t vl)
{ {
char *src; char *src;
PyObject *name, *value; PyObject *name, *value;
src = nxt_unit_sptr_get(&field->name); src = nxt_unit_sptr_get(&field->name);
name = PyString_FromStringAndSize(src, field->name_length); name = nxt_python_field_name(src, field->name_length);
if (nxt_slow_path(name == NULL)) { if (nxt_slow_path(name == NULL)) {
nxt_unit_req_error(ctx->req, nxt_unit_req_error(ctx->req,
"Python failed to create name string \"%.*s\"", "Python failed to create name string \"%.*s\"",
@@ -649,13 +671,13 @@ nxt_python_add_field(nxt_python_run_ctx_t *ctx, nxt_unit_field_t *field)
return NXT_UNIT_ERROR; return NXT_UNIT_ERROR;
} }
src = nxt_unit_sptr_get(&field->value); value = nxt_python_field_value(field, n, vl);
value = PyString_FromStringAndSize(src, field->value_length);
if (nxt_slow_path(value == NULL)) { if (nxt_slow_path(value == NULL)) {
nxt_unit_req_error(ctx->req, nxt_unit_req_error(ctx->req,
"Python failed to create value string \"%.*s\"", "Python failed to create value string \"%.*s\"",
(int) field->value_length, src); (int) field->value_length,
(char *) nxt_unit_sptr_get(&field->value));
nxt_python_print_exception(); nxt_python_print_exception();
goto fail; goto fail;
@@ -682,6 +704,80 @@ fail:
} }
static PyObject *
nxt_python_field_name(const char *name, uint8_t len)
{
char *p, c;
uint8_t i;
PyObject *res;
#if PY_MAJOR_VERSION == 3
res = PyUnicode_New(len + 5, 255);
#else
res = PyString_FromStringAndSize(NULL, len + 5);
#endif
if (nxt_slow_path(res == NULL)) {
return NULL;
}
p = PyString_AS_STRING(res);
p = nxt_cpymem(p, "HTTP_", 5);
for (i = 0; i < len; i++) {
c = name[i];
if (c >= 'a' && c <= 'z') {
*p++ = (c & ~0x20);
continue;
}
if (c == '-') {
*p++ = '_';
continue;
}
*p++ = c;
}
return res;
}
static PyObject *
nxt_python_field_value(nxt_unit_field_t *f, int n, uint32_t vl)
{
int i;
char *p, *src;
PyObject *res;
#if PY_MAJOR_VERSION == 3
res = PyUnicode_New(vl, 255);
#else
res = PyString_FromStringAndSize(NULL, vl);
#endif
if (nxt_slow_path(res == NULL)) {
return NULL;
}
p = PyString_AS_STRING(res);
src = nxt_unit_sptr_get(&f->value);
p = nxt_cpymem(p, src, f->value_length);
for (i = 1; i < n; i++) {
p = nxt_cpymem(p, ", ", 2);
src = nxt_unit_sptr_get(&f[i].value);
p = nxt_cpymem(p, src, f[i].value_length);
}
return res;
}
static int static int
nxt_python_add_obj(nxt_python_run_ctx_t *ctx, PyObject *name, PyObject *value) nxt_python_add_obj(nxt_python_run_ctx_t *ctx, PyObject *name, PyObject *value)
{ {