From b00983369be5f356280168b4c5d600bd7d614c60 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 29 Sep 2022 20:59:43 +0100 Subject: Renamed a couple of members of nxt_unit_request_t. This is a preparatory patch that renames the 'local' and 'local_length' members of the nxt_unit_request_t structure to 'local_addr' and 'local_addr_length' in preparation for the adding of 'local_port' and 'local_port_length' members. Suggested-by: Zhidao HONG Signed-off-by: Andrew Clayton --- src/python/nxt_python_asgi.c | 2 +- src/python/nxt_python_wsgi.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/python') diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 4ad0857d..40ea5e24 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -674,7 +674,7 @@ nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req) SET_ITEM(scope, client, v) Py_DECREF(v); - v = nxt_py_asgi_create_address(&r->local, r->local_length, 80); + v = nxt_py_asgi_create_address(&r->local_addr, r->local_addr_length, 80); if (nxt_slow_path(v == NULL)) { nxt_unit_req_alert(req, "Python failed to create 'server' pair"); goto fail; diff --git a/src/python/nxt_python_wsgi.c b/src/python/nxt_python_wsgi.c index 87dcfaa2..3fb6ac3b 100644 --- a/src/python/nxt_python_wsgi.c +++ b/src/python/nxt_python_wsgi.c @@ -609,8 +609,8 @@ nxt_python_get_environ(nxt_python_ctx_t *pctx) RC(nxt_python_add_sptr(pctx, nxt_py_remote_addr_str, &r->remote, r->remote_length)); - RC(nxt_python_add_sptr(pctx, nxt_py_server_addr_str, &r->local, - r->local_length)); + RC(nxt_python_add_sptr(pctx, nxt_py_server_addr_str, &r->local_addr, + r->local_addr_length)); if (r->tls) { RC(nxt_python_add_obj(pctx, nxt_py_wsgi_uri_scheme_str, -- cgit From 40d75c94a039f35505975736bb4f907ec456c9bd Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 15 Nov 2022 00:17:32 +0000 Subject: Optimization for the "--no-unix-sockets" case. --- src/python/nxt_python_asgi.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'src/python') diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 40ea5e24..256bcdcc 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -738,42 +738,40 @@ fail: static PyObject * nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port) { +#if (NXT_HAVE_UNIX_DOMAIN) size_t prefix_len; - nxt_str_t addr; PyObject *pair, *v; + nxt_str_t addr; addr.length = len; addr.start = nxt_unit_sptr_get(sptr); prefix_len = nxt_length("unix:"); - if (!nxt_str_start(&addr, "unix:", prefix_len)) { - return nxt_py_asgi_create_ip_address(sptr, len, port); - } + if (nxt_str_start(&addr, "unix:", prefix_len)) { -#if NXT_HAVE_UNIX_DOMAIN - pair = PyTuple_New(2); - if (nxt_slow_path(pair == NULL)) { - return NULL; - } + pair = PyTuple_New(2); + if (nxt_slow_path(pair == NULL)) { + return NULL; + } - addr.start += prefix_len; - addr.length -= prefix_len; + addr.start += prefix_len; + addr.length -= prefix_len; - v = PyString_FromStringAndSize((const char *) addr.start, addr.length); - if (nxt_slow_path(v == NULL)) { - Py_DECREF(pair); + v = PyString_FromStringAndSize((const char *) addr.start, addr.length); + if (nxt_slow_path(v == NULL)) { + Py_DECREF(pair); - return NULL; - } + return NULL; + } - PyTuple_SET_ITEM(pair, 0, v); - PyTuple_SET_ITEM(pair, 1, Py_None); + PyTuple_SET_ITEM(pair, 0, v); + PyTuple_SET_ITEM(pair, 1, Py_None); - return pair; + return pair; + } -#else - return NULL; #endif + return nxt_py_asgi_create_ip_address(sptr, len, port); } -- cgit From 3b970ed9345ee2fe27f15b43ff827630d38cc124 Mon Sep 17 00:00:00 2001 From: OutOfFocus4 Date: Tue, 13 Sep 2022 10:36:46 -0400 Subject: Removed dead code. Signed-off-by: Alejandro Colomar --- src/python/nxt_python.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/python') diff --git a/src/python/nxt_python.c b/src/python/nxt_python.c index 188c4920..37204051 100644 --- a/src/python/nxt_python.c +++ b/src/python/nxt_python.c @@ -70,7 +70,7 @@ nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) int rc; size_t len, size; uint32_t next; - PyObject *obj, *module; + PyObject *obj; nxt_str_t proto, probe_proto, name; nxt_int_t ret, n, i; nxt_unit_ctx_t *unit_ctx; @@ -154,7 +154,6 @@ nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) } #endif - module = NULL; obj = NULL; python_init.ctx_data = NULL; @@ -307,7 +306,6 @@ fail: } Py_XDECREF(obj); - Py_XDECREF(module); nxt_python_atexit(); -- cgit From 6902cd14ad4e322be1c29564bc2e238d0a225e92 Mon Sep 17 00:00:00 2001 From: OutOfFocus4 Date: Sun, 6 Nov 2022 09:08:55 -0500 Subject: Refactored functions that set WSGI variables. Splitting `nxt_python_add_sptr` into several functions will make future additions easier. Signed-off-by: Alejandro Colomar --- src/python/nxt_python_wsgi.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'src/python') diff --git a/src/python/nxt_python_wsgi.c b/src/python/nxt_python_wsgi.c index 3fb6ac3b..34afd9a9 100644 --- a/src/python/nxt_python_wsgi.c +++ b/src/python/nxt_python_wsgi.c @@ -63,6 +63,10 @@ static PyObject *nxt_python_copy_environ(nxt_unit_request_info_t *req); 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_char(nxt_python_ctx_t *pctx, PyObject *name, + char *src, uint32_t size); +static int nxt_python_add_py_string(nxt_python_ctx_t *pctx, PyObject *name, + PyObject *value); 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); @@ -692,10 +696,16 @@ static int nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, nxt_unit_sptr_t *sptr, uint32_t size) { - char *src; - PyObject *value; + return nxt_python_add_char(pctx, name, nxt_unit_sptr_get(sptr), size); +} - src = nxt_unit_sptr_get(sptr); + +static int +nxt_python_add_char(nxt_python_ctx_t *pctx, PyObject *name, + char *src, uint32_t size) +{ + int res; + PyObject *value; value = PyString_FromStringAndSize(src, size); if (nxt_slow_path(value == NULL)) { @@ -707,17 +717,25 @@ nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, return NXT_UNIT_ERROR; } + res = nxt_python_add_py_string(pctx, name, value); + + Py_DECREF(value); + + return res; +} + + +static int nxt_python_add_py_string(nxt_python_ctx_t *pctx, PyObject *name, + PyObject *value) +{ 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); return NXT_UNIT_ERROR; } - Py_DECREF(value); - return NXT_UNIT_OK; } -- cgit From 491d0f700f5690eba0f1fcf2124f3a37ef73eb1a Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 17 Nov 2022 21:56:58 +0000 Subject: Python: Added support for Python 3.11. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Python 3.8 added a new Python initialisation configuration API[0]. Python 3.11 marked the old API as deprecated resulting in the following compiler warnings which we treat as errors, failing the build src/python/nxt_python.c: In function ‘nxt_python_start’: src/python/nxt_python.c:130:13: error: ‘Py_SetProgramName’ is deprecated [-Werror=deprecated-declarations] 130 | Py_SetProgramName(nxt_py_home); | ^~~~~~~~~~~~~~~~~ In file included from /opt/python-3.11/include/python3.11/Python.h:94, from src/python/nxt_python.c:7: /opt/python-3.11/include/python3.11/pylifecycle.h:37:38: note: declared here 37 | Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *); | ^~~~~~~~~~~~~~~~~ src/python/nxt_python.c:134:13: error: ‘Py_SetPythonHome’ is deprecated [-Werror=deprecated-declarations] 134 | Py_SetPythonHome(nxt_py_home); | ^~~~~~~~~~~~~~~~ /opt/python-3.11/include/python3.11/pylifecycle.h:40:38: note: declared here 40 | Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetPythonHome(const wchar_t *); | ^~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors We actually have a few config scenarios: Python < 3, Python >= 3.0 < 3.8 and for Python 3 we have two configs where we select one based on virtual environment setup. Factor out the Python 3 config initialisation into its own function. We actually create two functions, one for Python 3.8+ and one for older Python 3. We pick the right function to use at build time. The new API also has error checking (where the old API doesn't) which we handle. [0]: https://peps.python.org/pep-0587/ Closes: [ Andrew: Expanded upon patch from @sandeep-gh ] Signed-off-by: Andrew Clayton --- src/python/nxt_python.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) (limited to 'src/python') diff --git a/src/python/nxt_python.c b/src/python/nxt_python.c index 37204051..8983815c 100644 --- a/src/python/nxt_python.c +++ b/src/python/nxt_python.c @@ -22,6 +22,10 @@ typedef struct { } nxt_py_thread_info_t; +#if PY_MAJOR_VERSION == 3 +static nxt_int_t nxt_python3_init_config(nxt_int_t pep405); +#endif + static nxt_int_t nxt_python_start(nxt_task_t *task, nxt_process_data_t *data); static nxt_int_t nxt_python_set_target(nxt_task_t *task, @@ -64,6 +68,63 @@ static nxt_py_thread_info_t *nxt_py_threads; static nxt_python_proto_t nxt_py_proto; +#if PY_VERSION_HEX >= NXT_PYTHON_VER(3, 8) + +static nxt_int_t +nxt_python3_init_config(nxt_int_t pep405) +{ + PyStatus status; + PyConfig config; + + PyConfig_InitIsolatedConfig(&config); + + if (pep405) { + status = PyConfig_SetString(&config, &config.program_name, + nxt_py_home); + if (PyStatus_Exception(status)) { + goto pyinit_exception; + } + + } else { + status =PyConfig_SetString(&config, &config.home, nxt_py_home); + if (PyStatus_Exception(status)) { + goto pyinit_exception; + } + } + + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + goto pyinit_exception; + } + PyConfig_Clear(&config); + + return NXT_OK; + +pyinit_exception: + + PyConfig_Clear(&config); + + return NXT_ERROR; +} + +#elif PY_MAJOR_VERSION == 3 + +static nxt_int_t +nxt_python3_init_config(nxt_int_t pep405) +{ + if (pep405) { + Py_SetProgramName(nxt_py_home); + + } else { + Py_SetPythonHome(nxt_py_home); + } + + return NXT_OK; +} + +#endif + + static nxt_int_t nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) { @@ -127,11 +188,15 @@ nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) if (pep405) { mbstowcs(nxt_py_home, c->home, len); mbstowcs(nxt_py_home + len, bin_python, sizeof(bin_python)); - Py_SetProgramName(nxt_py_home); } else { mbstowcs(nxt_py_home, c->home, len + 1); - Py_SetPythonHome(nxt_py_home); + } + + ret = nxt_python3_init_config(pep405); + if (nxt_slow_path(ret == NXT_ERROR)) { + nxt_alert(task, "Failed to initialise config"); + return NXT_ERROR; } #else -- cgit From 6dae517ebd20baa2066541e703d6aa594326dd69 Mon Sep 17 00:00:00 2001 From: OutOfFocus4 Date: Sun, 14 Nov 2021 10:47:07 -0500 Subject: Python: Added "prefix" to configuration. This patch gives users the option to set a `"prefix"` attribute for Python applications, either at the top level or for specific `"target"`s. If the attribute is present, the value of `"prefix"` must be a string beginning with `"/"`. If the value of the `"prefix"` attribute is longer than 1 character and ends in `"/"`, the trailing `"/"` is stripped. The purpose of the `"prefix"` attribute is to set the `SCRIPT_NAME` context value for WSGI applications and the `root_path` context value for ASGI applications, allowing applications to properly route requests regardless of the path that the server uses to expose the application. The context value is only set if the request's URL path begins with the value of the `"prefix"` attribute. In all other cases, the `SCRIPT_NAME` or `root_path` values are not set. In addition, for WSGI applications, the value of `"prefix"` will be stripped from the beginning of the request's URL path before it is sent to the application. Reviewed-by: Andrei Zeliankou Reviewed-by: Artem Konev Signed-off-by: Alejandro Colomar --- src/python/nxt_python.c | 60 ++++++++++++++++++++++++++++++++++++++-- src/python/nxt_python.h | 2 ++ src/python/nxt_python_asgi.c | 28 ++++++++++++++----- src/python/nxt_python_asgi_str.c | 2 +- src/python/nxt_python_wsgi.c | 49 +++++++++++++++++++++++--------- 5 files changed, 118 insertions(+), 23 deletions(-) (limited to 'src/python') diff --git a/src/python/nxt_python.c b/src/python/nxt_python.c index 8983815c..bdb04579 100644 --- a/src/python/nxt_python.c +++ b/src/python/nxt_python.c @@ -30,6 +30,8 @@ static nxt_int_t nxt_python_start(nxt_task_t *task, nxt_process_data_t *data); static nxt_int_t nxt_python_set_target(nxt_task_t *task, nxt_python_target_t *target, nxt_conf_value_t *conf); +nxt_inline nxt_int_t nxt_python_set_prefix(nxt_task_t *task, + nxt_python_target_t *target, nxt_conf_value_t *value); static nxt_int_t nxt_python_set_path(nxt_task_t *task, nxt_conf_value_t *value); static int nxt_python_init_threads(nxt_python_app_conf_t *c); static int nxt_python_ready_handler(nxt_unit_ctx_t *ctx); @@ -389,6 +391,7 @@ nxt_python_set_target(nxt_task_t *task, nxt_python_target_t *target, static nxt_str_t module_str = nxt_string("module"); static nxt_str_t callable_str = nxt_string("callable"); + static nxt_str_t prefix_str = nxt_string("prefix"); module = obj = NULL; @@ -436,6 +439,11 @@ nxt_python_set_target(nxt_task_t *task, nxt_python_target_t *target, goto fail; } + value = nxt_conf_get_object_member(conf, &prefix_str, NULL); + if (nxt_slow_path(nxt_python_set_prefix(task, target, value) != NXT_OK)) { + goto fail; + } + target->application = obj; obj = NULL; @@ -453,6 +461,48 @@ fail: } +nxt_inline nxt_int_t +nxt_python_set_prefix(nxt_task_t *task, nxt_python_target_t *target, + nxt_conf_value_t *value) +{ + u_char *prefix; + nxt_str_t str; + + if (value == NULL) { + return NXT_OK; + } + + nxt_conf_get_string(value, &str); + + if (str.length == 0) { + return NXT_OK; + } + + if (str.start[str.length - 1] == '/') { + str.length--; + } + target->prefix.length = str.length; + prefix = nxt_malloc(str.length); + if (nxt_slow_path(prefix == NULL)) { + nxt_alert(task, "Failed to allocate target prefix string"); + return NXT_ERROR; + } + + target->py_prefix = PyString_FromStringAndSize((char *)str.start, + str.length); + if (nxt_slow_path(target->py_prefix == NULL)) { + nxt_free(prefix); + nxt_alert(task, "Python failed to allocate target prefix " + "string"); + return NXT_ERROR; + } + nxt_memcpy(prefix, str.start, str.length); + target->prefix.start = prefix; + + return NXT_OK; +} + + static nxt_int_t nxt_python_set_path(nxt_task_t *task, nxt_conf_value_t *value) { @@ -730,7 +780,8 @@ nxt_python_done_strings(nxt_python_string_t *pstr) static void nxt_python_atexit(void) { - nxt_int_t i; + nxt_int_t i; + nxt_python_target_t *target; if (nxt_py_proto.done != NULL) { nxt_py_proto.done(); @@ -740,7 +791,12 @@ nxt_python_atexit(void) if (nxt_py_targets != NULL) { for (i = 0; i < nxt_py_targets->count; i++) { - Py_XDECREF(nxt_py_targets->target[i].application); + target = &nxt_py_targets->target[i]; + + Py_XDECREF(target->application); + Py_XDECREF(target->py_prefix); + + nxt_free(target->prefix.start); } nxt_unit_free(NULL, nxt_py_targets); diff --git a/src/python/nxt_python.h b/src/python/nxt_python.h index eddb1cfc..37e6265e 100644 --- a/src/python/nxt_python.h +++ b/src/python/nxt_python.h @@ -40,6 +40,8 @@ typedef struct { PyObject *application; + PyObject *py_prefix; + nxt_str_t prefix; nxt_bool_t asgi_legacy; } nxt_python_target_t; diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 256bcdcc..587a17cf 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -27,7 +27,8 @@ static void nxt_py_asgi_remove_reader(nxt_unit_ctx_t *ctx, static void nxt_py_asgi_request_handler(nxt_unit_request_info_t *req); static void nxt_py_asgi_close_handler(nxt_unit_request_info_t *req); -static PyObject *nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req); +static PyObject *nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req, + nxt_python_target_t *app_target); static PyObject *nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port); static PyObject *nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, @@ -455,16 +456,16 @@ nxt_py_asgi_request_handler(nxt_unit_request_info_t *req) goto release_send; } - scope = nxt_py_asgi_create_http_scope(req); + req->data = asgi; + target = &nxt_py_targets->target[req->request->app_target]; + + scope = nxt_py_asgi_create_http_scope(req, target); if (nxt_slow_path(scope == NULL)) { nxt_unit_request_done(req, NXT_UNIT_ERROR); goto release_done; } - req->data = asgi; - target = &nxt_py_targets->target[req->request->app_target]; - if (!target->asgi_legacy) { nxt_unit_req_debug(req, "Python call ASGI 3.0 application"); @@ -573,12 +574,14 @@ nxt_py_asgi_close_handler(nxt_unit_request_info_t *req) static PyObject * -nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req) +nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req, + nxt_python_target_t *app_target) { char *p, *target, *query; - uint32_t target_length, i; + uint32_t target_length, i, path_length; PyObject *scope, *v, *type, *scheme; PyObject *headers, *header; + nxt_str_t prefix; nxt_unit_field_t *f; nxt_unit_request_t *r; @@ -612,6 +615,17 @@ nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req) return NULL; } + prefix = app_target->prefix; + path_length = r->path_length; + p = nxt_unit_sptr_get(&r->path); + if (prefix.length > 0 + && ((path_length > prefix.length && p[prefix.length] == '/') + || path_length == prefix.length) + && memcmp(prefix.start, p, prefix.length) == 0) + { + SET_ITEM(scope, root_path, app_target->py_prefix); + } + p = nxt_unit_sptr_get(&r->version); SET_ITEM(scope, http_version, p[7] == '1' ? nxt_py_1_1_str : nxt_py_1_0_str) diff --git a/src/python/nxt_python_asgi_str.c b/src/python/nxt_python_asgi_str.c index 34422973..7171d52b 100644 --- a/src/python/nxt_python_asgi_str.c +++ b/src/python/nxt_python_asgi_str.c @@ -99,7 +99,7 @@ static nxt_python_string_t nxt_py_asgi_strings[] = { { nxt_string("query_string"), &nxt_py_query_string_str }, { nxt_string("raw_path"), &nxt_py_raw_path_str }, { nxt_string("result"), &nxt_py_result_str }, - { nxt_string("root_path"), &nxt_py_root_path_str }, // not used + { nxt_string("root_path"), &nxt_py_root_path_str }, { nxt_string("scheme"), &nxt_py_scheme_str }, { nxt_string("server"), &nxt_py_server_str }, { nxt_string("set_exception"), &nxt_py_set_exception_str }, diff --git a/src/python/nxt_python_wsgi.c b/src/python/nxt_python_wsgi.c index 34afd9a9..dfb31509 100644 --- a/src/python/nxt_python_wsgi.c +++ b/src/python/nxt_python_wsgi.c @@ -60,7 +60,8 @@ static void nxt_python_request_handler(nxt_unit_request_info_t *req); static PyObject *nxt_python_create_environ(nxt_python_app_conf_t *c); static PyObject *nxt_python_copy_environ(nxt_unit_request_info_t *req); -static PyObject *nxt_python_get_environ(nxt_python_ctx_t *pctx); +static PyObject *nxt_python_get_environ(nxt_python_ctx_t *pctx, + nxt_python_target_t *app_target); 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_char(nxt_python_ctx_t *pctx, PyObject *name, @@ -141,6 +142,7 @@ static PyObject *nxt_py_query_string_str; static PyObject *nxt_py_remote_addr_str; static PyObject *nxt_py_request_method_str; static PyObject *nxt_py_request_uri_str; +static PyObject *nxt_py_script_name_str; static PyObject *nxt_py_server_addr_str; static PyObject *nxt_py_server_name_str; static PyObject *nxt_py_server_port_str; @@ -160,6 +162,7 @@ static nxt_python_string_t nxt_python_strings[] = { { nxt_string("REMOTE_ADDR"), &nxt_py_remote_addr_str }, { nxt_string("REQUEST_METHOD"), &nxt_py_request_method_str }, { nxt_string("REQUEST_URI"), &nxt_py_request_uri_str }, + { nxt_string("SCRIPT_NAME"), &nxt_py_script_name_str }, { nxt_string("SERVER_ADDR"), &nxt_py_server_addr_str }, { nxt_string("SERVER_NAME"), &nxt_py_server_name_str }, { nxt_string("SERVER_PORT"), &nxt_py_server_port_str }, @@ -304,11 +307,12 @@ 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, *application; - nxt_bool_t prepare_environ; - nxt_python_ctx_t *pctx; + int rc; + PyObject *environ, *args, *response, *iterator, *item; + PyObject *close, *result; + nxt_bool_t prepare_environ; + nxt_python_ctx_t *pctx; + nxt_python_target_t *target; pctx = req->ctx->data; @@ -331,7 +335,9 @@ nxt_python_request_handler(nxt_unit_request_info_t *req) prepare_environ = 1; - environ = nxt_python_get_environ(pctx); + target = &nxt_py_targets->target[req->request->app_target]; + + environ = nxt_python_get_environ(pctx, target); if (nxt_slow_path(environ == NULL)) { rc = NXT_UNIT_ERROR; goto done; @@ -352,8 +358,7 @@ nxt_python_request_handler(nxt_unit_request_info_t *req) Py_INCREF(pctx->start_resp); PyTuple_SET_ITEM(args, 1, pctx->start_resp); - application = nxt_py_targets->target[req->request->app_target].application; - response = PyObject_CallObject(application, args); + response = PyObject_CallObject(target->application, args); Py_DECREF(args); @@ -584,11 +589,14 @@ nxt_python_copy_environ(nxt_unit_request_info_t *req) static PyObject * -nxt_python_get_environ(nxt_python_ctx_t *pctx) +nxt_python_get_environ(nxt_python_ctx_t *pctx, + nxt_python_target_t *app_target) { int rc; - uint32_t i, j, vl; + char *path; + uint32_t i, j, vl, path_length; PyObject *environ; + nxt_str_t prefix; nxt_unit_field_t *f, *f2; nxt_unit_request_t *r; @@ -608,8 +616,23 @@ nxt_python_get_environ(nxt_python_ctx_t *pctx) r->target_length)); RC(nxt_python_add_sptr(pctx, nxt_py_query_string_str, &r->query, r->query_length)); - RC(nxt_python_add_sptr(pctx, nxt_py_path_info_str, &r->path, - r->path_length)); + + prefix = app_target->prefix; + path_length = r->path_length; + path = nxt_unit_sptr_get(&r->path); + if (prefix.length > 0 + && ((path_length > prefix.length && path[prefix.length] == '/') + || path_length == prefix.length) + && memcmp(prefix.start, path, prefix.length) == 0) + { + RC(nxt_python_add_py_string(pctx, nxt_py_script_name_str, + app_target->py_prefix)); + + path += prefix.length; + path_length -= prefix.length; + } + + RC(nxt_python_add_char(pctx, nxt_py_path_info_str, path, path_length)); RC(nxt_python_add_sptr(pctx, nxt_py_remote_addr_str, &r->remote, r->remote_length)); -- cgit