diff options
Diffstat (limited to 'src/python/nxt_python_wsgi.c')
-rw-r--r-- | src/python/nxt_python_wsgi.c | 448 |
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; |