mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-04-28 19:03:37 +00:00
201 lines
4.9 KiB
C
201 lines
4.9 KiB
C
#include "uwsgi_python.h"
|
|
|
|
extern struct uwsgi_server uwsgi;
|
|
extern struct uwsgi_python up;
|
|
|
|
// check here
|
|
|
|
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_AsLatin1String(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_AsLatin1String(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_AsLatin1String(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;
|
|
}
|
|
|