PyObject *py_uwsgi_write(PyObject * self, PyObject * args) { PyObject *data; char *content; size_t content_len; struct wsgi_request *wsgi_req = py_current_wsgi_req(); data = PyTuple_GetItem(args, 0); if (PyString_Check(data)) { content = PyString_AsString(data); content_len = PyString_Size(data); UWSGI_RELEASE_GIL uwsgi_response_write_body_do(wsgi_req, content, content_len); UWSGI_GET_GIL // this is a special case for the write callable // no need to honout write-errors-exception-only if (wsgi_req->write_errors > uwsgi.write_errors_tolerance && !uwsgi.disable_write_exception) { uwsgi_py_write_set_exception(wsgi_req); return NULL; } } Py_INCREF(Py_None); return Py_None; }
PyObject *py_eventfd_write(PyObject * self, PyObject * args) { int fd, timeout = 0; struct wsgi_request *wsgi_req = py_current_wsgi_req(); if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) { return NULL; } if (async_add_fd_write(wsgi_req, fd, timeout)) { return PyErr_Format(PyExc_IOError, "unable to fd %d to the event queue", fd); } return PyString_FromString(""); }
PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) { PyObject *headers, *head; PyObject *h_key, *h_value; PyObject *exc_info = NULL; size_t i; struct wsgi_request *wsgi_req = py_current_wsgi_req(); // avoid double sending of headers if (wsgi_req->headers_sent) { return PyErr_Format(PyExc_IOError, "headers already sent"); } // this must be done before headers management if (PyTuple_Size(args) > 2) { exc_info = PyTuple_GetItem(args, 2); if (exc_info && exc_info != Py_None) { PyObject *exc_type = PyTuple_GetItem(exc_info, 0); PyObject *exc_val = PyTuple_GetItem(exc_info, 1); PyObject *exc_tb = PyTuple_GetItem(exc_info, 2); if (!exc_type || !exc_val || !exc_tb) { return NULL; } Py_INCREF(exc_type); Py_INCREF(exc_val); Py_INCREF(exc_tb); // in this way, error will be reported to the log PyErr_Restore(exc_type, exc_val, exc_tb); // the error is reported, let's continue... // return NULL } } head = PyTuple_GetItem(args, 0); if (!head) { return PyErr_Format(PyExc_TypeError, "start_response() takes at least 2 arguments"); } #ifdef PYTHREE // check for web3 if ((self != Py_None && !PyUnicode_Check(head)) || (self == Py_None && !PyBytes_Check(head))) { #else if (!PyString_Check(head)) { #endif return PyErr_Format(PyExc_TypeError, "http status must be a string"); } char *status_line = NULL; size_t status_line_len = 0; #ifdef PYTHREE PyObject *zero = NULL; PyObject *zero2 = NULL; if (self != Py_None) { zero = PyUnicode_AsASCIIString(head); if (!zero) { return PyErr_Format(PyExc_TypeError, "http status string must be encodable in latin1"); } status_line = PyBytes_AsString(zero); status_line_len = PyBytes_Size(zero); } else { status_line = PyBytes_AsString(head); status_line_len = PyBytes_Size(head); } #else status_line = PyString_AsString(head); status_line_len = PyString_Size(head); #endif if (uwsgi_response_prepare_headers(wsgi_req, status_line, status_line_len)) { #ifdef PYTHREE Py_DECREF(zero); #endif goto end; } #ifdef PYTHREE Py_DECREF(zero); #endif headers = PyTuple_GetItem(args, 1); if (!headers) { return PyErr_Format(PyExc_TypeError, "start_response() takes at least 2 arguments"); } if (!PyList_Check(headers)) { return PyErr_Format(PyExc_TypeError, "http headers must be in a python list"); } size_t h_count = PyList_Size(headers); for (i = 0; i < h_count; i++) { head = PyList_GetItem(headers, i); if (!head) { return NULL; } if (!PyTuple_Check(head)) { return PyErr_Format(PyExc_TypeError, "http header must be defined in a tuple"); } h_key = PyTuple_GetItem(head, 0); if (!h_key) { return PyErr_Format(PyExc_TypeError, "http header must be a 2-item tuple"); } #ifdef PYTHREE if ((self != Py_None && !PyUnicode_Check(h_key)) || (self == Py_None && !PyBytes_Check(h_key))) { #else if (!PyString_Check(h_key)) { #endif return PyErr_Format(PyExc_TypeError, "http header key must be a string"); } h_value = PyTuple_GetItem(head, 1); if (!h_value) { return PyErr_Format(PyExc_TypeError, "http header must be a 2-item tuple"); } #ifdef PYTHREE if ((self != Py_None && !PyUnicode_Check(h_value)) || (self == Py_None && !PyBytes_Check(h_value))) { #else if (!PyString_Check(h_value)) { #endif return PyErr_Format(PyExc_TypeError, "http header value must be a string"); } char *k = NULL; size_t kl = 0; char *v = NULL; size_t vl = 0; #ifdef PYTHREE if (self != Py_None) { zero = PyUnicode_AsASCIIString(h_key); if (!zero) { return PyErr_Format(PyExc_TypeError, "http header must be encodable in latin1"); } k = PyBytes_AsString(zero); kl = PyBytes_Size(zero); } else { k = PyBytes_AsString(h_key); kl = PyBytes_Size(h_key); } #else k = PyString_AsString(h_key); kl = PyString_Size(h_key); #endif #ifdef PYTHREE if (self != Py_None) { zero2 = PyUnicode_AsASCIIString(h_value); if (!zero2) { return PyErr_Format(PyExc_TypeError, "http header must be encodable in latin1"); } v = PyBytes_AsString(zero2); vl = PyBytes_Size(zero2); } else { v = PyBytes_AsString(h_value); vl = PyBytes_Size(h_value); } #else v = PyString_AsString(h_value); vl = PyString_Size(h_value); #endif if (uwsgi_response_add_header(wsgi_req, k, kl, v, vl)) { #ifdef PYTHREE Py_DECREF(zero); Py_DECREF(zero2); #endif return PyErr_Format(PyExc_TypeError, "unable to add header to the response"); } #ifdef PYTHREE Py_DECREF(zero); Py_DECREF(zero2); #endif } if (up.start_response_nodelay) { UWSGI_RELEASE_GIL if (uwsgi_response_write_headers_do(wsgi_req)) { UWSGI_GET_GIL return PyErr_Format(PyExc_IOError, "unable to directly send headers"); } UWSGI_GET_GIL } end: Py_INCREF(up.wsgi_writeout); return up.wsgi_writeout; }