diff options
author | Alexander Borisov <alexander.borisov@nginx.com> | 2018-04-19 17:35:07 +0300 |
---|---|---|
committer | Alexander Borisov <alexander.borisov@nginx.com> | 2018-04-19 17:35:07 +0300 |
commit | da22c2ca96d9484eb4e95536fd6276967868114e (patch) | |
tree | ab8637876fc1e9c1e27468270bd0ffae3fec5303 | |
parent | b06a0c95d08d3a3752353f5098e98ed3014170e6 (diff) | |
download | unit-da22c2ca96d9484eb4e95536fd6276967868114e.tar.gz unit-da22c2ca96d9484eb4e95536fd6276967868114e.tar.bz2 |
Python: returning write() callable object from start_response().
According to PEP (3)333 the start_respose() function must return
a write() callable.
This closes #107 issue on GitHub.
-rw-r--r-- | src/nxt_python_wsgi.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/src/nxt_python_wsgi.c b/src/nxt_python_wsgi.c index 7d805703..1c1cf03d 100644 --- a/src/nxt_python_wsgi.c +++ b/src/nxt_python_wsgi.c @@ -35,9 +35,13 @@ #if PY_MAJOR_VERSION == 3 +#define NXT_PYTHON_BYTES_TYPE "bytestring" + #define PyString_FromString PyUnicode_FromString #define PyString_FromStringAndSize PyUnicode_FromStringAndSize #else +#define NXT_PYTHON_BYTES_TYPE "string" + #define PyBytes_FromString PyString_FromString #define PyBytes_FromStringAndSize PyString_FromStringAndSize #define PyBytes_Check PyString_Check @@ -69,6 +73,7 @@ static PyObject *nxt_python_get_environ(nxt_task_t *task, nxt_app_rmsg_t *rmsg, nxt_python_run_ctx_t *ctx); static PyObject *nxt_py_start_resp(PyObject *self, PyObject *args); +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); @@ -112,6 +117,11 @@ static PyMethodDef nxt_py_start_resp_method[] = { }; +static PyMethodDef nxt_py_write_method[] = { + {"unit_write", nxt_py_write, METH_O, ""} +}; + + static PyMethodDef nxt_py_input_methods[] = { { "read", (PyCFunction) nxt_py_input_read, METH_VARARGS, 0 }, { "readline", (PyCFunction) nxt_py_input_readline, METH_VARARGS, 0 }, @@ -176,6 +186,7 @@ static PyTypeObject nxt_py_input_type = { static PyObject *nxt_py_application; static PyObject *nxt_py_start_resp_obj; +static PyObject *nxt_py_write_obj; static PyObject *nxt_py_environ_ptyp; #if PY_MAJOR_VERSION == 3 @@ -263,6 +274,15 @@ nxt_python_init(nxt_task_t *task, nxt_common_app_conf_t *conf) nxt_py_start_resp_obj = obj; + 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; + } + + nxt_py_write_obj = obj; + obj = nxt_python_create_environ(task); if (obj == NULL) { @@ -456,6 +476,7 @@ nxt_python_atexit(nxt_task_t *task) { Py_DECREF(nxt_py_application); Py_DECREF(nxt_py_start_resp_obj); + Py_DECREF(nxt_py_write_obj); Py_DECREF(nxt_py_environ_ptyp); Py_Finalize(); @@ -845,7 +866,32 @@ nxt_py_start_resp(PyObject *self, PyObject *args) /* flush headers */ nxt_python_write(ctx, cr_lf, sizeof(cr_lf) - 1, 1, 0); - return args; + Py_INCREF(nxt_py_write_obj); + return nxt_py_write_obj; +} + + +static PyObject * +nxt_py_write(PyObject *self, PyObject *str) +{ + nxt_int_t rc; + + if (nxt_fast_path(!PyBytes_Check(str))) { + return PyErr_Format(PyExc_TypeError, "the argument is not a %s", + NXT_PYTHON_BYTES_TYPE); + } + + rc = nxt_app_msg_write_raw(nxt_python_run_ctx->task, + nxt_python_run_ctx->wmsg, + (const u_char *) PyBytes_AS_STRING(str), + PyBytes_GET_SIZE(str)); + + if (nxt_slow_path(rc != NXT_OK)) { + return PyErr_Format(PyExc_RuntimeError, + "failed to write response value"); + } + + Py_RETURN_NONE; } |