summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_python_wsgi.c
diff options
context:
space:
mode:
authorAlexander Borisov <alexander.borisov@nginx.com>2018-04-19 17:35:07 +0300
committerAlexander Borisov <alexander.borisov@nginx.com>2018-04-19 17:35:07 +0300
commitda22c2ca96d9484eb4e95536fd6276967868114e (patch)
treeab8637876fc1e9c1e27468270bd0ffae3fec5303 /src/nxt_python_wsgi.c
parentb06a0c95d08d3a3752353f5098e98ed3014170e6 (diff)
downloadunit-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.
Diffstat (limited to '')
-rw-r--r--src/nxt_python_wsgi.c48
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;
}