1
#include "uwsgi_python.h"
3
extern struct uwsgi_server uwsgi;
4
extern struct uwsgi_python up;
5
extern PyTypeObject uwsgi_InputType;
8
extern struct http_status_codes hsc[];
11
void *uwsgi_request_subhandler_pump(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
16
PyObject *pydictkey, *pydictvalue;
18
char *port = memchr(wsgi_req->host, ':', wsgi_req->host_len);
21
zero = PyString_FromStringAndSize(wsgi_req->host, (port-wsgi_req->host));
22
PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero);
25
zero = PyString_FromStringAndSize(port, wsgi_req->host_len-((port+1)-wsgi_req->host));
26
PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero);
31
zero = PyString_FromStringAndSize(wsgi_req->host, wsgi_req->host_len);
32
PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero);
35
zero = PyString_FromStringAndSize("80", 2);
36
PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero);
40
zero = PyString_FromStringAndSize(wsgi_req->remote_addr, wsgi_req->remote_addr_len);
41
PyDict_SetItemString(wsgi_req->async_environ, "remote_addr", zero);
44
zero = PyString_FromStringAndSize(wsgi_req->path_info, wsgi_req->path_info_len);
45
PyDict_SetItemString(wsgi_req->async_environ, "uri", zero);
48
if (wsgi_req->query_string_len > 0) {
49
zero = PyString_FromStringAndSize(wsgi_req->query_string, wsgi_req->query_string_len);
50
PyDict_SetItemString(wsgi_req->async_environ, "query_string", zero);
54
zero = PyString_FromStringAndSize(uwsgi_lower(wsgi_req->method, wsgi_req->method_len), wsgi_req->method_len);
55
PyDict_SetItemString(wsgi_req->async_environ, "method", zero);
58
if (wsgi_req->post_cl > 0) {
59
PyDict_SetItemString(wsgi_req->async_environ, "content_length", PyInt_FromLong(wsgi_req->post_cl));
60
if (wsgi_req->content_type_len > 0) {
61
zero = PyString_FromStringAndSize(wsgi_req->content_type, wsgi_req->content_type_len);
62
PyDict_SetItemString(wsgi_req->async_environ, "content_type", zero);
69
PyObject *headers = PyDict_New();
71
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
73
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
75
if (wsgi_req->hvec[i].iov_len < 6) continue;
76
if (!uwsgi_startswith(wsgi_req->hvec[i].iov_base, "HTTP_", 5)) {
77
(void) uwsgi_lower(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5);
79
pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5, NULL);
80
pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
82
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5);
83
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
85
PyObject *old_value = PyDict_GetItem(headers, pydictkey);
87
if (PyString_Check(old_value)) {
88
PyObject *new_value = PyList_New(0);
89
PyList_Append(new_value, old_value);
90
old_value = new_value;
91
PyDict_SetItem(headers, pydictkey, old_value);
94
PyList_Append(old_value, pydictvalue);
97
PyDict_SetItem(headers, pydictkey, pydictvalue);
100
Py_DECREF(pydictvalue);
104
PyDict_SetItemString(wsgi_req->async_environ, "headers", headers);
107
// if async_post is mapped as a file, directly use it as wsgi.input
108
if (wsgi_req->async_post) {
110
wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "pump_body", "rb", 0, NULL, NULL, NULL, 0);
112
wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "pump_body", "r", NULL);
116
// create wsgi.input custom object
117
wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
118
((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
119
((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
120
((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
121
((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;
125
PyDict_SetItemString(wsgi_req->async_environ, "body", wsgi_req->async_input);
128
if (wsgi_req->scheme_len > 0) {
129
zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
131
else if (wsgi_req->https_len > 0) {
132
if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
133
zero = PyString_FromString("https");
136
zero = PyString_FromString("http");
140
zero = PyString_FromString("http");
142
PyDict_SetItemString(wsgi_req->async_environ, "scheme", zero);
146
wsgi_req->async_app = wi->callable;
148
// export .env only in non-threaded mode
149
if (uwsgi.threads < 2) {
150
PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
153
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
155
if (uwsgi.cores > 1) {
156
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
160
if (uwsgi.cluster_fd >= 0) {
161
zero = PyString_FromString(uwsgi.cluster);
162
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
164
zero = PyString_FromString(uwsgi.hostname);
165
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", zero);
169
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
174
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
175
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
179
int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
185
struct http_status_codes *http_sc;
191
if (!wsgi_req->async_placeholder) {
192
if (PyDict_Check((PyObject *)wsgi_req->async_result)) {
195
PyObject *status = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "status");
197
uwsgi_log("invalid Pump response (status code).\n");
201
PyObject *headers = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "headers");
203
uwsgi_log("invalid Pump response (headers).\n");
208
wsgi_req->async_placeholder = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "body");
209
if (!wsgi_req->async_placeholder) {
210
uwsgi_log("invalid Pump response (body).\n");
214
// get the status code
215
if (!PyInt_Check(status)) {
216
uwsgi_log("invalid Pump response (status code).\n");
220
if (uwsgi_num2str2n(PyInt_AsLong(status), sc, 4) != 3) {
221
uwsgi_log("invalid Pump response (status code).\n");
226
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
227
if (http_sc->key[0] == sc[0] && http_sc->key[1] == sc[1] && http_sc->key[2] == sc[2]) {
228
wsgi_req->hvec[4].iov_base = (char *) http_sc->message;
229
wsgi_req->hvec[4].iov_len = http_sc->message_size;
236
uwsgi_log("invalid Pump response (status code).\n");
240
wsgi_req->hvec[0].iov_base = wsgi_req->protocol;
241
wsgi_req->hvec[0].iov_len = wsgi_req->protocol_len;
242
wsgi_req->hvec[1].iov_base = " ";
243
wsgi_req->hvec[1].iov_len = 1;
244
wsgi_req->hvec[2].iov_base = sc;
245
wsgi_req->hvec[2].iov_len = 3;
246
wsgi_req->hvec[3].iov_base = " ";
247
wsgi_req->hvec[3].iov_len = 1;
248
wsgi_req->hvec[5].iov_base = "\r\n";
249
wsgi_req->hvec[5].iov_len = 2;
252
wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 6);
255
uwsgi_error("writev()");
257
wsgi_req->headers_size += wsize;
259
PyObject *hhkey, *hhvalue;
260
#ifdef UWSGI_PYTHON_OLD
263
Py_ssize_t hhpos = 0;
265
while (PyDict_Next(headers, &hhpos, &hhkey, &hhvalue)) {
266
if (!PyString_Check(hhkey)) continue;
268
wsgi_req->hvec[0].iov_base = PyString_AsString(hhkey);
269
wsgi_req->hvec[0].iov_len = PyString_Size(hhkey);
270
((char*)wsgi_req->hvec[0].iov_base)[0] = toupper((int) ((char*)wsgi_req->hvec[0].iov_base)[0]);
272
wsgi_req->hvec[1].iov_base = ": ";
273
wsgi_req->hvec[1].iov_len = 2;
275
wsgi_req->hvec[3].iov_base = "\r\n";
276
wsgi_req->hvec[3].iov_len = 2;
277
if (PyList_Check(hhvalue)) {
278
for(i=0;i<PyList_Size(hhvalue);i++) {
279
PyObject *item = PyList_GetItem(hhvalue, i);
280
if (PyString_Check(item)) {
281
wsgi_req->hvec[2].iov_base = PyString_AsString(item);
282
wsgi_req->hvec[2].iov_len = PyString_Size(item);
284
wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 4);
287
uwsgi_error("writev()");
289
wsgi_req->headers_size += wsize;
293
else if (PyString_Check(hhvalue)) {
294
wsgi_req->hvec[2].iov_base = PyString_AsString(hhvalue);
295
wsgi_req->hvec[2].iov_len = PyString_Size(hhvalue);
297
wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 4);
300
uwsgi_error("writev()");
302
wsgi_req->headers_size += wsize;
306
wsgi_req->socket->proto_write(wsgi_req, "\r\n", 2);
307
Py_INCREF((PyObject *)wsgi_req->async_placeholder);
309
if (PyString_Check((PyObject *)wsgi_req->async_placeholder)) {
310
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(wsgi_req->async_placeholder), PyString_Size(wsgi_req->async_placeholder))) < 0) {
311
uwsgi_error("write()");
314
wsgi_req->response_size += wsize;
318
else if ((wsgi_req->sendfile_fd = PyObject_AsFileDescriptor((PyObject *)wsgi_req->async_placeholder)) > -1) {
320
else if (PyFile_Check((PyObject *)wsgi_req->async_placeholder)) {
321
wsgi_req->sendfile_fd = fileno(PyFile_AsFile((PyObject *)wsgi_req->async_placeholder));
323
wsize = uwsgi_sendfile(wsgi_req);
327
wsgi_req->response_size += wsize;
331
PyObject *tmp = (PyObject *)wsgi_req->async_placeholder;
333
wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_placeholder );
337
if (!wsgi_req->async_placeholder) {
341
if (uwsgi.async > 1) {
348
uwsgi_log("invalid Pump response.\n");
355
pychunk = PyIter_Next(wsgi_req->async_placeholder);
358
if (PyErr_Occurred()) PyErr_Print();
363
if (PyString_Check(pychunk)) {
364
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
365
uwsgi_error("write()");
369
wsgi_req->response_size += wsize;
378
if (wsgi_req->async_input) {
379
Py_DECREF((PyObject *)wsgi_req->async_input);
381
if (wsgi_req->async_environ) {
382
PyDict_Clear(wsgi_req->async_environ);
384
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
386
Py_DECREF((PyObject *)wsgi_req->async_result);