summaryrefslogtreecommitdiffhomepage
path: root/src/python/nxt_python_wsgi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/python/nxt_python_wsgi.c')
-rw-r--r--src/python/nxt_python_wsgi.c448
1 files changed, 244 insertions, 204 deletions
diff --git a/src/python/nxt_python_wsgi.c b/src/python/nxt_python_wsgi.c
index 97030cd3..da7b183c 100644
--- a/src/python/nxt_python_wsgi.c
+++ b/src/python/nxt_python_wsgi.c
@@ -38,55 +38,57 @@
*/
-typedef struct nxt_python_run_ctx_s nxt_python_run_ctx_t;
-
typedef struct {
PyObject_HEAD
-} nxt_py_input_t;
+ uint64_t content_length;
+ uint64_t bytes_sent;
+ PyObject *environ;
+ PyObject *start_resp;
+ PyObject *write;
+ nxt_unit_request_info_t *req;
+ PyThreadState *thread_state;
+} nxt_python_ctx_t;
-typedef struct {
- PyObject_HEAD
-} nxt_py_error_t;
+
+static int nxt_python_wsgi_ctx_data_alloc(void **pdata);
+static void nxt_python_wsgi_ctx_data_free(void *data);
+static int nxt_python_wsgi_run(nxt_unit_ctx_t *ctx);
+static void nxt_python_wsgi_done(void);
static void nxt_python_request_handler(nxt_unit_request_info_t *req);
-static PyObject *nxt_python_create_environ(nxt_task_t *task);
-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 PyObject *nxt_python_create_environ(nxt_python_app_conf_t *c);
+static PyObject *nxt_python_get_environ(nxt_python_ctx_t *pctx);
+static int nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name,
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_ctx_t *pctx,
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_ctx_t *pctx, PyObject *name,
PyObject *value);
static PyObject *nxt_py_start_resp(PyObject *self, PyObject *args);
-static int nxt_python_response_add_field(nxt_python_run_ctx_t *ctx,
+static int nxt_python_response_add_field(nxt_python_ctx_t *pctx,
PyObject *name, PyObject *value, int i);
static int nxt_python_str_buf(PyObject *str, char **buf, uint32_t *len,
PyObject **bytes);
static PyObject *nxt_py_write(PyObject *self, PyObject *args);
-static void nxt_py_input_dealloc(nxt_py_input_t *self);
-static PyObject *nxt_py_input_read(nxt_py_input_t *self, PyObject *args);
-static PyObject *nxt_py_input_readline(nxt_py_input_t *self, PyObject *args);
-static PyObject *nxt_py_input_getline(nxt_python_run_ctx_t *ctx, size_t size);
-static PyObject *nxt_py_input_readlines(nxt_py_input_t *self, PyObject *args);
+static void nxt_py_input_dealloc(nxt_python_ctx_t *pctx);
+static PyObject *nxt_py_input_read(nxt_python_ctx_t *pctx, PyObject *args);
+static PyObject *nxt_py_input_readline(nxt_python_ctx_t *pctx,
+ PyObject *args);
+static PyObject *nxt_py_input_getline(nxt_python_ctx_t *pctx, size_t size);
+static PyObject *nxt_py_input_readlines(nxt_python_ctx_t *self,
+ PyObject *args);
-static PyObject *nxt_py_input_iter(PyObject *self);
-static PyObject *nxt_py_input_next(PyObject *self);
+static PyObject *nxt_py_input_iter(PyObject *pctx);
+static PyObject *nxt_py_input_next(PyObject *pctx);
-static int nxt_python_write(nxt_python_run_ctx_t *ctx, PyObject *bytes);
-
-struct nxt_python_run_ctx_s {
- uint64_t content_length;
- uint64_t bytes_sent;
- PyObject *environ;
- nxt_unit_request_info_t *req;
-};
+static int nxt_python_write(nxt_python_ctx_t *pctx, PyObject *bytes);
static PyMethodDef nxt_py_start_resp_method[] = {
@@ -111,7 +113,7 @@ static PyTypeObject nxt_py_input_type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "unit._input",
- .tp_basicsize = sizeof(nxt_py_input_t),
+ .tp_basicsize = sizeof(nxt_python_ctx_t),
.tp_dealloc = (destructor) nxt_py_input_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = "unit input object.",
@@ -121,12 +123,7 @@ static PyTypeObject nxt_py_input_type = {
};
-static PyObject *nxt_py_start_resp_obj;
-static PyObject *nxt_py_write_obj;
-static PyObject *nxt_py_environ_ptyp;
-
-static PyThreadState *nxt_python_thread_state;
-static nxt_python_run_ctx_t *nxt_python_run_ctx;
+static PyObject *nxt_py_environ_ptyp;
static PyObject *nxt_py_80_str;
static PyObject *nxt_py_close_str;
@@ -143,6 +140,7 @@ static PyObject *nxt_py_server_addr_str;
static PyObject *nxt_py_server_name_str;
static PyObject *nxt_py_server_port_str;
static PyObject *nxt_py_server_protocol_str;
+static PyObject *nxt_py_wsgi_input_str;
static PyObject *nxt_py_wsgi_uri_scheme_str;
static nxt_python_string_t nxt_python_strings[] = {
@@ -161,82 +159,132 @@ static nxt_python_string_t nxt_python_strings[] = {
{ nxt_string("SERVER_NAME"), &nxt_py_server_name_str },
{ nxt_string("SERVER_PORT"), &nxt_py_server_port_str },
{ nxt_string("SERVER_PROTOCOL"), &nxt_py_server_protocol_str },
+ { nxt_string("wsgi.input"), &nxt_py_wsgi_input_str },
{ nxt_string("wsgi.url_scheme"), &nxt_py_wsgi_uri_scheme_str },
{ nxt_null_string, NULL },
};
+static nxt_python_proto_t nxt_py_wsgi_proto = {
+ .ctx_data_alloc = nxt_python_wsgi_ctx_data_alloc,
+ .ctx_data_free = nxt_python_wsgi_ctx_data_free,
+ .run = nxt_python_wsgi_run,
+ .done = nxt_python_wsgi_done,
+};
+
-nxt_int_t
-nxt_python_wsgi_init(nxt_task_t *task, nxt_unit_init_t *init)
+int
+nxt_python_wsgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto)
{
PyObject *obj;
obj = NULL;
- if (nxt_slow_path(nxt_python_init_strings(nxt_python_strings) != NXT_OK)) {
- nxt_alert(task, "Python failed to init string objects");
+ if (nxt_slow_path(nxt_python_init_strings(nxt_python_strings)
+ != NXT_UNIT_OK))
+ {
+ nxt_unit_alert(NULL, "Python failed to init string objects");
goto fail;
}
- obj = PyCFunction_New(nxt_py_start_resp_method, NULL);
+ obj = nxt_python_create_environ(init->data);
if (nxt_slow_path(obj == NULL)) {
- nxt_alert(task,
- "Python failed to initialize the \"start_response\" function");
goto fail;
}
- nxt_py_start_resp_obj = obj;
+ nxt_py_environ_ptyp = obj;
+ obj = NULL;
+
+ init->callbacks.request_handler = nxt_python_request_handler;
+
+ *proto = nxt_py_wsgi_proto;
- obj = PyCFunction_New(nxt_py_write_method, NULL);
- if (nxt_slow_path(obj == NULL)) {
- nxt_alert(task, "Python failed to initialize the \"write\" function");
- goto fail;
+ return NXT_UNIT_OK;
+
+fail:
+
+ Py_XDECREF(obj);
+
+ return NXT_UNIT_ERROR;
+}
+
+
+static int
+nxt_python_wsgi_ctx_data_alloc(void **pdata)
+{
+ nxt_python_ctx_t *pctx;
+
+ pctx = PyObject_New(nxt_python_ctx_t, &nxt_py_input_type);
+ if (nxt_slow_path(pctx == NULL)) {
+ nxt_unit_alert(NULL,
+ "Python failed to create the \"wsgi.input\" object");
+ return NXT_UNIT_ERROR;
}
- nxt_py_write_obj = obj;
+ pctx->write = NULL;
- obj = nxt_python_create_environ(task);
- if (nxt_slow_path(obj == NULL)) {
+ pctx->start_resp = PyCFunction_New(nxt_py_start_resp_method,
+ (PyObject *) pctx);
+ if (nxt_slow_path(pctx->start_resp == NULL)) {
+ nxt_unit_alert(NULL,
+ "Python failed to initialize the \"start_response\" function");
goto fail;
}
- nxt_py_environ_ptyp = obj;
- obj = NULL;
+ pctx->write = PyCFunction_New(nxt_py_write_method, (PyObject *) pctx);
+ if (nxt_slow_path(pctx->write == NULL)) {
+ nxt_unit_alert(NULL,
+ "Python failed to initialize the \"write\" function");
+ goto fail;
+ }
- init->callbacks.request_handler = nxt_python_request_handler;
+ *pdata = pctx;
- return NXT_OK;
+ return NXT_UNIT_OK;
fail:
- Py_XDECREF(obj);
+ nxt_python_wsgi_ctx_data_free(pctx);
- return NXT_ERROR;
+ return NXT_UNIT_ERROR;
}
-int
+static void
+nxt_python_wsgi_ctx_data_free(void *data)
+{
+ nxt_python_ctx_t *pctx;
+
+ pctx = data;
+
+ Py_XDECREF(pctx->start_resp);
+ Py_XDECREF(pctx->write);
+ Py_XDECREF(pctx);
+}
+
+
+static int
nxt_python_wsgi_run(nxt_unit_ctx_t *ctx)
{
- int rc;
+ int rc;
+ nxt_python_ctx_t *pctx;
- nxt_python_thread_state = PyEval_SaveThread();
+ pctx = ctx->data;
+
+ pctx->thread_state = PyEval_SaveThread();
rc = nxt_unit_run(ctx);
- PyEval_RestoreThread(nxt_python_thread_state);
+ PyEval_RestoreThread(pctx->thread_state);
return rc;
}
-void
+static void
nxt_python_wsgi_done(void)
{
nxt_python_done_strings(nxt_python_strings);
- Py_XDECREF(nxt_py_start_resp_obj);
- Py_XDECREF(nxt_py_write_obj);
Py_XDECREF(nxt_py_environ_ptyp);
}
@@ -244,14 +292,20 @@ nxt_python_wsgi_done(void)
static void
nxt_python_request_handler(nxt_unit_request_info_t *req)
{
- int rc;
- PyObject *environ, *args, *response, *iterator, *item;
- PyObject *close, *result;
- nxt_python_run_ctx_t run_ctx = {-1, 0, NULL, req};
+ int rc;
+ PyObject *environ, *args, *response, *iterator, *item;
+ PyObject *close, *result;
+ nxt_python_ctx_t *pctx;
- PyEval_RestoreThread(nxt_python_thread_state);
+ pctx = req->ctx->data;
- environ = nxt_python_get_environ(&run_ctx);
+ pctx->content_length = -1;
+ pctx->bytes_sent = 0;
+ pctx->req = req;
+
+ PyEval_RestoreThread(pctx->thread_state);
+
+ environ = nxt_python_get_environ(pctx);
if (nxt_slow_path(environ == NULL)) {
rc = NXT_UNIT_ERROR;
goto done;
@@ -269,10 +323,8 @@ nxt_python_request_handler(nxt_unit_request_info_t *req)
PyTuple_SET_ITEM(args, 0, environ);
- Py_INCREF(nxt_py_start_resp_obj);
- PyTuple_SET_ITEM(args, 1, nxt_py_start_resp_obj);
-
- nxt_python_run_ctx = &run_ctx;
+ Py_INCREF(pctx->start_resp);
+ PyTuple_SET_ITEM(args, 1, pctx->start_resp);
response = PyObject_CallObject(nxt_py_application, args);
@@ -288,7 +340,7 @@ nxt_python_request_handler(nxt_unit_request_info_t *req)
/* Shortcut: avoid iterate over response string symbols. */
if (PyBytes_Check(response)) {
- rc = nxt_python_write(&run_ctx, response);
+ rc = nxt_python_write(pctx, response);
} else {
iterator = PyObject_GetIter(response);
@@ -296,7 +348,7 @@ nxt_python_request_handler(nxt_unit_request_info_t *req)
if (nxt_fast_path(iterator != NULL)) {
rc = NXT_UNIT_OK;
- while (run_ctx.bytes_sent < run_ctx.content_length) {
+ while (pctx->bytes_sent < pctx->content_length) {
item = PyIter_Next(iterator);
if (item == NULL) {
@@ -312,7 +364,7 @@ nxt_python_request_handler(nxt_unit_request_info_t *req)
}
if (nxt_fast_path(PyBytes_Check(item))) {
- rc = nxt_python_write(&run_ctx, item);
+ rc = nxt_python_write(pctx, item);
} else {
nxt_unit_req_error(req, "the application returned "
@@ -361,29 +413,31 @@ nxt_python_request_handler(nxt_unit_request_info_t *req)
done:
- nxt_python_thread_state = PyEval_SaveThread();
+ pctx->thread_state = PyEval_SaveThread();
+
+ pctx->req = NULL;
- nxt_python_run_ctx = NULL;
nxt_unit_request_done(req, rc);
}
static PyObject *
-nxt_python_create_environ(nxt_task_t *task)
+nxt_python_create_environ(nxt_python_app_conf_t *c)
{
PyObject *obj, *err, *environ;
environ = PyDict_New();
if (nxt_slow_path(environ == NULL)) {
- nxt_alert(task, "Python failed to create the \"environ\" dictionary");
+ nxt_unit_alert(NULL,
+ "Python failed to create the \"environ\" dictionary");
return NULL;
}
obj = PyString_FromStringAndSize((char *) nxt_server.start,
nxt_server.length);
if (nxt_slow_path(obj == NULL)) {
- nxt_alert(task,
+ nxt_unit_alert(NULL,
"Python failed to create the \"SERVER_SOFTWARE\" environ value");
goto fail;
}
@@ -391,7 +445,7 @@ nxt_python_create_environ(nxt_task_t *task)
if (nxt_slow_path(PyDict_SetItemString(environ, "SERVER_SOFTWARE", obj)
!= 0))
{
- nxt_alert(task,
+ nxt_unit_alert(NULL,
"Python failed to set the \"SERVER_SOFTWARE\" environ value");
goto fail;
}
@@ -401,15 +455,15 @@ nxt_python_create_environ(nxt_task_t *task)
obj = Py_BuildValue("(ii)", 1, 0);
if (nxt_slow_path(obj == NULL)) {
- nxt_alert(task,
+ nxt_unit_alert(NULL,
"Python failed to build the \"wsgi.version\" environ value");
goto fail;
}
if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.version", obj) != 0))
{
- nxt_alert(task,
- "Python failed to set the \"wsgi.version\" environ value");
+ nxt_unit_alert(NULL,
+ "Python failed to set the \"wsgi.version\" environ value");
goto fail;
}
@@ -418,10 +472,10 @@ nxt_python_create_environ(nxt_task_t *task)
if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.multithread",
- Py_False)
+ c->threads > 1 ? Py_True : Py_False)
!= 0))
{
- nxt_alert(task,
+ nxt_unit_alert(NULL,
"Python failed to set the \"wsgi.multithread\" environ value");
goto fail;
}
@@ -430,7 +484,7 @@ nxt_python_create_environ(nxt_task_t *task)
Py_True)
!= 0))
{
- nxt_alert(task,
+ nxt_unit_alert(NULL,
"Python failed to set the \"wsgi.multiprocess\" environ value");
goto fail;
}
@@ -439,46 +493,30 @@ nxt_python_create_environ(nxt_task_t *task)
Py_False)
!= 0))
{
- nxt_alert(task,
+ nxt_unit_alert(NULL,
"Python failed to set the \"wsgi.run_once\" environ value");
goto fail;
}
if (nxt_slow_path(PyType_Ready(&nxt_py_input_type) != 0)) {
- nxt_alert(task,
+ nxt_unit_alert(NULL,
"Python failed to initialize the \"wsgi.input\" type object");
goto fail;
}
- obj = (PyObject *) PyObject_New(nxt_py_input_t, &nxt_py_input_type);
-
- if (nxt_slow_path(obj == NULL)) {
- nxt_alert(task, "Python failed to create the \"wsgi.input\" object");
- goto fail;
- }
-
- if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.input", obj) != 0)) {
- nxt_alert(task,
- "Python failed to set the \"wsgi.input\" environ value");
- goto fail;
- }
-
- Py_DECREF(obj);
- obj = NULL;
-
err = PySys_GetObject((char *) "stderr");
if (nxt_slow_path(err == NULL)) {
- nxt_alert(task, "Python failed to get \"sys.stderr\" object");
+ nxt_unit_alert(NULL, "Python failed to get \"sys.stderr\" object");
goto fail;
}
if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.errors", err) != 0))
{
- nxt_alert(task,
- "Python failed to set the \"wsgi.errors\" environ value");
+ nxt_unit_alert(NULL,
+ "Python failed to set the \"wsgi.errors\" environ value");
goto fail;
}
@@ -494,7 +532,7 @@ fail:
static PyObject *
-nxt_python_get_environ(nxt_python_run_ctx_t *ctx)
+nxt_python_get_environ(nxt_python_ctx_t *pctx)
{
int rc;
uint32_t i, j, vl;
@@ -504,15 +542,15 @@ nxt_python_get_environ(nxt_python_run_ctx_t *ctx)
environ = PyDict_Copy(nxt_py_environ_ptyp);
if (nxt_slow_path(environ == NULL)) {
- nxt_unit_req_error(ctx->req,
+ nxt_unit_req_error(pctx->req,
"Python failed to copy the \"environ\" dictionary");
return NULL;
}
- ctx->environ = environ;
+ pctx->environ = environ;
- r = ctx->req->request;
+ r = pctx->req->request;
#define RC(S) \
do { \
@@ -522,36 +560,36 @@ nxt_python_get_environ(nxt_python_run_ctx_t *ctx)
} \
} while(0)
- RC(nxt_python_add_sptr(ctx, nxt_py_request_method_str, &r->method,
+ RC(nxt_python_add_sptr(pctx, nxt_py_request_method_str, &r->method,
r->method_length));
- RC(nxt_python_add_sptr(ctx, nxt_py_request_uri_str, &r->target,
+ RC(nxt_python_add_sptr(pctx, nxt_py_request_uri_str, &r->target,
r->target_length));
- RC(nxt_python_add_sptr(ctx, nxt_py_query_string_str, &r->query,
+ RC(nxt_python_add_sptr(pctx, nxt_py_query_string_str, &r->query,
r->query_length));
- RC(nxt_python_add_sptr(ctx, nxt_py_path_info_str, &r->path,
+ RC(nxt_python_add_sptr(pctx, nxt_py_path_info_str, &r->path,
r->path_length));
- RC(nxt_python_add_sptr(ctx, nxt_py_remote_addr_str, &r->remote,
+ RC(nxt_python_add_sptr(pctx, nxt_py_remote_addr_str, &r->remote,
r->remote_length));
- RC(nxt_python_add_sptr(ctx, nxt_py_server_addr_str, &r->local,
+ RC(nxt_python_add_sptr(pctx, nxt_py_server_addr_str, &r->local,
r->local_length));
if (r->tls) {
- RC(nxt_python_add_obj(ctx, nxt_py_wsgi_uri_scheme_str,
+ RC(nxt_python_add_obj(pctx, nxt_py_wsgi_uri_scheme_str,
nxt_py_https_str));
} else {
- RC(nxt_python_add_obj(ctx, nxt_py_wsgi_uri_scheme_str,
+ RC(nxt_python_add_obj(pctx, nxt_py_wsgi_uri_scheme_str,
nxt_py_http_str));
}
- RC(nxt_python_add_sptr(ctx, nxt_py_server_protocol_str, &r->version,
+ RC(nxt_python_add_sptr(pctx, nxt_py_server_protocol_str, &r->version,
r->version_length));
- RC(nxt_python_add_sptr(ctx, nxt_py_server_name_str, &r->server_name,
+ RC(nxt_python_add_sptr(pctx, nxt_py_server_name_str, &r->server_name,
r->server_name_length));
- RC(nxt_python_add_obj(ctx, nxt_py_server_port_str, nxt_py_80_str));
+ RC(nxt_python_add_obj(pctx, nxt_py_server_port_str, nxt_py_80_str));
- nxt_unit_request_group_dup_fields(ctx->req);
+ nxt_unit_request_group_dup_fields(pctx->req);
for (i = 0; i < r->fields_count;) {
f = r->fields + i;
@@ -569,7 +607,7 @@ nxt_python_get_environ(nxt_python_run_ctx_t *ctx)
vl += 2 + f2->value_length;
}
- RC(nxt_python_add_field(ctx, f, j - i, vl));
+ RC(nxt_python_add_field(pctx, f, j - i, vl));
i = j;
}
@@ -577,19 +615,27 @@ nxt_python_get_environ(nxt_python_run_ctx_t *ctx)
if (r->content_length_field != NXT_UNIT_NONE_FIELD) {
f = r->fields + r->content_length_field;
- RC(nxt_python_add_sptr(ctx, nxt_py_content_length_str, &f->value,
+ RC(nxt_python_add_sptr(pctx, nxt_py_content_length_str, &f->value,
f->value_length));
}
if (r->content_type_field != NXT_UNIT_NONE_FIELD) {
f = r->fields + r->content_type_field;
- RC(nxt_python_add_sptr(ctx, nxt_py_content_type_str, &f->value,
+ RC(nxt_python_add_sptr(pctx, nxt_py_content_type_str, &f->value,
f->value_length));
}
#undef RC
+ if (nxt_slow_path(PyDict_SetItem(environ, nxt_py_wsgi_input_str,
+ (PyObject *) pctx) != 0))
+ {
+ nxt_unit_req_error(pctx->req,
+ "Python failed to set the \"wsgi.input\" environ value");
+ goto fail;
+ }
+
return environ;
fail:
@@ -601,7 +647,7 @@ fail:
static int
-nxt_python_add_sptr(nxt_python_run_ctx_t *ctx, PyObject *name,
+nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name,
nxt_unit_sptr_t *sptr, uint32_t size)
{
char *src;
@@ -611,7 +657,7 @@ nxt_python_add_sptr(nxt_python_run_ctx_t *ctx, PyObject *name,
value = PyString_FromStringAndSize(src, size);
if (nxt_slow_path(value == NULL)) {
- nxt_unit_req_error(ctx->req,
+ nxt_unit_req_error(pctx->req,
"Python failed to create value string \"%.*s\"",
(int) size, src);
nxt_python_print_exception();
@@ -619,8 +665,8 @@ nxt_python_add_sptr(nxt_python_run_ctx_t *ctx, PyObject *name,
return NXT_UNIT_ERROR;
}
- if (nxt_slow_path(PyDict_SetItem(ctx->environ, name, value) != 0)) {
- nxt_unit_req_error(ctx->req,
+ if (nxt_slow_path(PyDict_SetItem(pctx->environ, name, value) != 0)) {
+ nxt_unit_req_error(pctx->req,
"Python failed to set the \"%s\" environ value",
PyUnicode_AsUTF8(name));
Py_DECREF(value);
@@ -635,7 +681,7 @@ nxt_python_add_sptr(nxt_python_run_ctx_t *ctx, PyObject *name,
static int
-nxt_python_add_field(nxt_python_run_ctx_t *ctx, nxt_unit_field_t *field, int n,
+nxt_python_add_field(nxt_python_ctx_t *pctx, nxt_unit_field_t *field, int n,
uint32_t vl)
{
char *src;
@@ -645,7 +691,7 @@ nxt_python_add_field(nxt_python_run_ctx_t *ctx, nxt_unit_field_t *field, int n,
name = nxt_python_field_name(src, field->name_length);
if (nxt_slow_path(name == NULL)) {
- nxt_unit_req_error(ctx->req,
+ nxt_unit_req_error(pctx->req,
"Python failed to create name string \"%.*s\"",
(int) field->name_length, src);
nxt_python_print_exception();
@@ -656,7 +702,7 @@ nxt_python_add_field(nxt_python_run_ctx_t *ctx, nxt_unit_field_t *field, int n,
value = nxt_python_field_value(field, n, vl);
if (nxt_slow_path(value == NULL)) {
- nxt_unit_req_error(ctx->req,
+ nxt_unit_req_error(pctx->req,
"Python failed to create value string \"%.*s\"",
(int) field->value_length,
(char *) nxt_unit_sptr_get(&field->value));
@@ -665,8 +711,8 @@ nxt_python_add_field(nxt_python_run_ctx_t *ctx, nxt_unit_field_t *field, int n,
goto fail;
}
- if (nxt_slow_path(PyDict_SetItem(ctx->environ, name, value) != 0)) {
- nxt_unit_req_error(ctx->req,
+ if (nxt_slow_path(PyDict_SetItem(pctx->environ, name, value) != 0)) {
+ nxt_unit_req_error(pctx->req,
"Python failed to set the \"%s\" environ value",
PyUnicode_AsUTF8(name));
goto fail;
@@ -761,10 +807,10 @@ 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, PyObject *value)
+nxt_python_add_obj(nxt_python_ctx_t *pctx, PyObject *name, PyObject *value)
{
- if (nxt_slow_path(PyDict_SetItem(ctx->environ, name, value) != 0)) {
- nxt_unit_req_error(ctx->req,
+ if (nxt_slow_path(PyDict_SetItem(pctx->environ, name, value) != 0)) {
+ nxt_unit_req_error(pctx->req,
"Python failed to set the \"%s\" environ value",
PyUnicode_AsUTF8(name));
@@ -778,15 +824,15 @@ nxt_python_add_obj(nxt_python_run_ctx_t *ctx, PyObject *name, PyObject *value)
static PyObject *
nxt_py_start_resp(PyObject *self, PyObject *args)
{
- int rc, status;
- char *status_str, *space_ptr;
- uint32_t status_len;
- PyObject *headers, *tuple, *string, *status_bytes;
- Py_ssize_t i, n, fields_size, fields_count;
- nxt_python_run_ctx_t *ctx;
-
- ctx = nxt_python_run_ctx;
- if (nxt_slow_path(ctx == NULL)) {
+ int rc, status;
+ char *status_str, *space_ptr;
+ uint32_t status_len;
+ PyObject *headers, *tuple, *string, *status_bytes;
+ Py_ssize_t i, n, fields_size, fields_count;
+ nxt_python_ctx_t *pctx;
+
+ pctx = (nxt_python_ctx_t *) self;
+ if (nxt_slow_path(pctx->req == NULL)) {
return PyErr_Format(PyExc_RuntimeError,
"start_response() is called "
"outside of WSGI request processing");
@@ -831,7 +877,7 @@ nxt_py_start_resp(PyObject *self, PyObject *args)
fields_size += PyBytes_GET_SIZE(string);
} else if (PyUnicode_Check(string)) {
- fields_size += PyUnicode_GET_SIZE(string);
+ fields_size += PyUnicode_GET_LENGTH(string);
} else {
return PyErr_Format(PyExc_TypeError,
@@ -843,7 +889,7 @@ nxt_py_start_resp(PyObject *self, PyObject *args)
fields_size += PyBytes_GET_SIZE(string);
} else if (PyUnicode_Check(string)) {
- fields_size += PyUnicode_GET_SIZE(string);
+ fields_size += PyUnicode_GET_LENGTH(string);
} else {
return PyErr_Format(PyExc_TypeError,
@@ -851,7 +897,7 @@ nxt_py_start_resp(PyObject *self, PyObject *args)
}
}
- ctx->content_length = -1;
+ pctx->content_length = -1;
string = PyTuple_GET_ITEM(args, 0);
rc = nxt_python_str_buf(string, &status_str, &status_len, &status_bytes);
@@ -877,7 +923,7 @@ nxt_py_start_resp(PyObject *self, PyObject *args)
* ... applications can replace their originally intended output with error
* output, up until the last possible moment.
*/
- rc = nxt_unit_response_init(ctx->req, status, fields_count, fields_size);
+ rc = nxt_unit_response_init(pctx->req, status, fields_count, fields_size);
if (nxt_slow_path(rc != NXT_UNIT_OK)) {
return PyErr_Format(PyExc_RuntimeError,
"failed to allocate response object");
@@ -886,7 +932,7 @@ nxt_py_start_resp(PyObject *self, PyObject *args)
for (i = 0; i < fields_count; i++) {
tuple = PyList_GET_ITEM(headers, i);
- rc = nxt_python_response_add_field(ctx, PyTuple_GET_ITEM(tuple, 0),
+ rc = nxt_python_response_add_field(pctx, PyTuple_GET_ITEM(tuple, 0),
PyTuple_GET_ITEM(tuple, 1), i);
if (nxt_slow_path(rc != NXT_UNIT_OK)) {
return PyErr_Format(PyExc_RuntimeError,
@@ -907,21 +953,21 @@ nxt_py_start_resp(PyObject *self, PyObject *args)
* possible exception to this rule is if the response headers explicitly
* include a Content-Length of zero.)
*/
- if (ctx->content_length == 0) {
- rc = nxt_unit_response_send(ctx->req);
+ if (pctx->content_length == 0) {
+ rc = nxt_unit_response_send(pctx->req);
if (nxt_slow_path(rc != NXT_UNIT_OK)) {
return PyErr_Format(PyExc_RuntimeError,
"failed to send response headers");
}
}
- Py_INCREF(nxt_py_write_obj);
- return nxt_py_write_obj;
+ Py_INCREF(pctx->write);
+ return pctx->write;
}
static int
-nxt_python_response_add_field(nxt_python_run_ctx_t *ctx, PyObject *name,
+nxt_python_response_add_field(nxt_python_ctx_t *pctx, PyObject *name,
PyObject *value, int i)
{
int rc;
@@ -943,20 +989,20 @@ nxt_python_response_add_field(nxt_python_run_ctx_t *ctx, PyObject *name,
goto fail;
}
- rc = nxt_unit_response_add_field(ctx->req, name_str, name_length,
+ rc = nxt_unit_response_add_field(pctx->req, name_str, name_length,
value_str, value_length);
if (nxt_slow_path(rc != NXT_UNIT_OK)) {
goto fail;
}
- if (ctx->req->response->fields[i].hash == NXT_UNIT_HASH_CONTENT_LENGTH) {
+ if (pctx->req->response->fields[i].hash == NXT_UNIT_HASH_CONTENT_LENGTH) {
content_length = nxt_off_t_parse((u_char *) value_str, value_length);
if (nxt_slow_path(content_length < 0)) {
- nxt_unit_req_error(ctx->req, "failed to parse Content-Length "
+ nxt_unit_req_error(pctx->req, "failed to parse Content-Length "
"value %.*s", (int) value_length, value_str);
} else {
- ctx->content_length = content_length;
+ pctx->content_length = content_length;
}
}
@@ -1001,7 +1047,7 @@ nxt_py_write(PyObject *self, PyObject *str)
NXT_PYTHON_BYTES_TYPE);
}
- rc = nxt_python_write(nxt_python_run_ctx, str);
+ rc = nxt_python_write((nxt_python_ctx_t *) self, str);
if (nxt_slow_path(rc != NXT_UNIT_OK)) {
return PyErr_Format(PyExc_RuntimeError,
"failed to write response value");
@@ -1012,28 +1058,26 @@ nxt_py_write(PyObject *self, PyObject *str)
static void
-nxt_py_input_dealloc(nxt_py_input_t *self)
+nxt_py_input_dealloc(nxt_python_ctx_t *self)
{
PyObject_Del(self);
}
static PyObject *
-nxt_py_input_read(nxt_py_input_t *self, PyObject *args)
+nxt_py_input_read(nxt_python_ctx_t *pctx, PyObject *args)
{
- char *buf;
- PyObject *content, *obj;
- Py_ssize_t size, n;
- nxt_python_run_ctx_t *ctx;
+ char *buf;
+ PyObject *content, *obj;
+ Py_ssize_t size, n;
- ctx = nxt_python_run_ctx;
- if (nxt_slow_path(ctx == NULL)) {
+ if (nxt_slow_path(pctx->req == NULL)) {
return PyErr_Format(PyExc_RuntimeError,
"wsgi.input.read() is called "
"outside of WSGI request processing");
}
- size = ctx->req->content_length;
+ size = pctx->req->content_length;
n = PyTuple_GET_SIZE(args);
@@ -1057,8 +1101,8 @@ nxt_py_input_read(nxt_py_input_t *self, PyObject *args)
}
}
- if (size == -1 || size > (Py_ssize_t) ctx->req->content_length) {
- size = ctx->req->content_length;
+ if (size == -1 || size > (Py_ssize_t) pctx->req->content_length) {
+ size = pctx->req->content_length;
}
}
@@ -1069,22 +1113,20 @@ nxt_py_input_read(nxt_py_input_t *self, PyObject *args)
buf = PyBytes_AS_STRING(content);
- size = nxt_unit_request_read(ctx->req, buf, size);
+ size = nxt_unit_request_read(pctx->req, buf, size);
return content;
}
static PyObject *
-nxt_py_input_readline(nxt_py_input_t *self, PyObject *args)
+nxt_py_input_readline(nxt_python_ctx_t *pctx, PyObject *args)
{
- ssize_t ssize;
- PyObject *obj;
- Py_ssize_t n;
- nxt_python_run_ctx_t *ctx;
+ ssize_t ssize;
+ PyObject *obj;
+ Py_ssize_t n;
- ctx = nxt_python_run_ctx;
- if (nxt_slow_path(ctx == NULL)) {
+ if (nxt_slow_path(pctx->req == NULL)) {
return PyErr_Format(PyExc_RuntimeError,
"wsgi.input.readline() is called "
"outside of WSGI request processing");
@@ -1102,7 +1144,7 @@ nxt_py_input_readline(nxt_py_input_t *self, PyObject *args)
ssize = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
if (nxt_fast_path(ssize > 0)) {
- return nxt_py_input_getline(ctx, ssize);
+ return nxt_py_input_getline(pctx, ssize);
}
if (ssize == 0) {
@@ -1119,18 +1161,18 @@ nxt_py_input_readline(nxt_py_input_t *self, PyObject *args)
}
}
- return nxt_py_input_getline(ctx, SSIZE_MAX);
+ return nxt_py_input_getline(pctx, SSIZE_MAX);
}
static PyObject *
-nxt_py_input_getline(nxt_python_run_ctx_t *ctx, size_t size)
+nxt_py_input_getline(nxt_python_ctx_t *pctx, size_t size)
{
void *buf;
ssize_t res;
PyObject *content;
- res = nxt_unit_request_readline_size(ctx->req, size);
+ res = nxt_unit_request_readline_size(pctx->req, size);
if (nxt_slow_path(res < 0)) {
return NULL;
}
@@ -1146,20 +1188,18 @@ nxt_py_input_getline(nxt_python_run_ctx_t *ctx, size_t size)
buf = PyBytes_AS_STRING(content);
- res = nxt_unit_request_read(ctx->req, buf, res);
+ res = nxt_unit_request_read(pctx->req, buf, res);
return content;
}
static PyObject *
-nxt_py_input_readlines(nxt_py_input_t *self, PyObject *args)
+nxt_py_input_readlines(nxt_python_ctx_t *pctx, PyObject *args)
{
- PyObject *res;
- nxt_python_run_ctx_t *ctx;
+ PyObject *res;
- ctx = nxt_python_run_ctx;
- if (nxt_slow_path(ctx == NULL)) {
+ if (nxt_slow_path(pctx->req == NULL)) {
return PyErr_Format(PyExc_RuntimeError,
"wsgi.input.readlines() is called "
"outside of WSGI request processing");
@@ -1171,7 +1211,7 @@ nxt_py_input_readlines(nxt_py_input_t *self, PyObject *args)
}
for ( ;; ) {
- PyObject *line = nxt_py_input_getline(ctx, SSIZE_MAX);
+ PyObject *line = nxt_py_input_getline(pctx, SSIZE_MAX);
if (nxt_slow_path(line == NULL)) {
Py_DECREF(res);
return NULL;
@@ -1201,17 +1241,17 @@ nxt_py_input_iter(PyObject *self)
static PyObject *
nxt_py_input_next(PyObject *self)
{
- PyObject *line;
- nxt_python_run_ctx_t *ctx;
+ PyObject *line;
+ nxt_python_ctx_t *pctx;
- ctx = nxt_python_run_ctx;
- if (nxt_slow_path(ctx == NULL)) {
+ pctx = (nxt_python_ctx_t *) self;
+ if (nxt_slow_path(pctx->req == NULL)) {
return PyErr_Format(PyExc_RuntimeError,
"wsgi.input.next() is called "
"outside of WSGI request processing");
}
- line = nxt_py_input_getline(ctx, SSIZE_MAX);
+ line = nxt_py_input_getline(pctx, SSIZE_MAX);
if (nxt_slow_path(line == NULL)) {
return NULL;
}
@@ -1227,7 +1267,7 @@ nxt_py_input_next(PyObject *self)
static int
-nxt_python_write(nxt_python_run_ctx_t *ctx, PyObject *bytes)
+nxt_python_write(nxt_python_ctx_t *pctx, PyObject *bytes)
{
int rc;
char *str_buf;
@@ -1248,16 +1288,16 @@ nxt_python_write(nxt_python_run_ctx_t *ctx, PyObject *bytes)
* stop iterating over the response when enough data has been sent, or raise
* an error if the application tries to write() past that point.
*/
- if (nxt_slow_path(str_length > ctx->content_length - ctx->bytes_sent)) {
- nxt_unit_req_error(ctx->req, "content length %"PRIu64" exceeded",
- ctx->content_length);
+ if (nxt_slow_path(str_length > pctx->content_length - pctx->bytes_sent)) {
+ nxt_unit_req_error(pctx->req, "content length %"PRIu64" exceeded",
+ pctx->content_length);
return NXT_UNIT_ERROR;
}
- rc = nxt_unit_response_write(ctx->req, str_buf, str_length);
+ rc = nxt_unit_response_write(pctx->req, str_buf, str_length);
if (nxt_fast_path(rc == NXT_UNIT_OK)) {
- ctx->bytes_sent += str_length;
+ pctx->bytes_sent += str_length;
}
return rc;