~ubuntu-branches/ubuntu/trusty/uwsgi/trusty

« back to all changes in this revision

Viewing changes to plugins/python/pump_subhandler.c

  • Committer: Package Import Robot
  • Author(s): Janos Guljas
  • Date: 2012-02-13 03:43:28 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20120213034328-d02hz8m5pon6kaxf
Tags: 1.0.3+dfsg-1
* New upstream version.
* Adjust rack plugin LD_RUN_PATH patch.
* Adjust patch for uWSGI Control Center jQuery links in templates.
* Remove '-fno-strict-aliasing' CFLAG patch as it is implemented upstream.
* Remove fix indentation of uwsgidecorators_py patch as implemented upstream.
* Adjust init scripts to use top-bottom options order, as --inherit option
  is not working as in earlier versions. 
* Update debian/copyright file.
* Add LSB Description field to debian/uwsgi.init.d.
* Set Architecture to "all" for binary package uwsgi-extra because
  it contains no architecture dependent files.
* Change uwsgi description. (Closes: #640698)
* New binary packages:
  - uwsgi-plugin-carbon
  - uwsgi-plugin-graylog2
  - uwsgi-plugin-logsocket
  - uwsgi-plugin-probeconnect
  - uwsgi-plugin-probepg
  - uwsgi-plugin-rrdtool
  - uwsgi-plugin-rsyslog
  - uwsgi-plugin-signal
  - uwsgi-plugin-symcall
  - uwsgi-plugin-syslog
* python-uwsgidecorators:
  - fix binary-install rule to call dh_python2
  - remove debian/source.lintian-overrides
* uwsgi-plugin-jvm-openjdk-6:
  - fix FTBFS on armel and powerpc (Closes: #656280)
* uwsgi-plugin-python:
  - document issue "ImportError: No module named site" when using
    virtualenv with Python 2.6 in README.Debian (Closes: #654333)
* Adjust debian/watch uversionmangle option.
* Repack upstram source to remove minimized jQuery and jQuery UI JavaScript
  libraries:
  - add get-orig-source rule to debian/rules
  - append +dfsg to upstream version
  - update debian/watch with dversionmangle option

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "uwsgi_python.h"
 
2
 
 
3
extern struct uwsgi_server uwsgi;
 
4
extern struct uwsgi_python up;
 
5
extern PyTypeObject uwsgi_InputType;
 
6
 
 
7
 
 
8
extern struct http_status_codes hsc[];
 
9
 
 
10
 
 
11
void *uwsgi_request_subhandler_pump(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
 
12
 
 
13
        PyObject *zero;
 
14
 
 
15
        int i;
 
16
        PyObject *pydictkey, *pydictvalue;
 
17
 
 
18
        char *port = memchr(wsgi_req->host, ':', wsgi_req->host_len);
 
19
        if (port) {
 
20
 
 
21
                zero = PyString_FromStringAndSize(wsgi_req->host, (port-wsgi_req->host));
 
22
                PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero);
 
23
                Py_DECREF(zero);
 
24
 
 
25
                zero = PyString_FromStringAndSize(port, wsgi_req->host_len-((port+1)-wsgi_req->host));
 
26
                PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero);
 
27
                Py_DECREF(zero);
 
28
        }
 
29
        else {
 
30
 
 
31
                zero = PyString_FromStringAndSize(wsgi_req->host, wsgi_req->host_len);
 
32
                PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero);
 
33
                Py_DECREF(zero);
 
34
 
 
35
                zero = PyString_FromStringAndSize("80", 2);
 
36
                PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero);
 
37
                Py_DECREF(zero);
 
38
        }
 
39
 
 
40
        zero = PyString_FromStringAndSize(wsgi_req->remote_addr, wsgi_req->remote_addr_len);
 
41
        PyDict_SetItemString(wsgi_req->async_environ, "remote_addr", zero);
 
42
        Py_DECREF(zero);
 
43
 
 
44
        zero = PyString_FromStringAndSize(wsgi_req->path_info, wsgi_req->path_info_len);
 
45
        PyDict_SetItemString(wsgi_req->async_environ, "uri", zero);
 
46
        Py_DECREF(zero);
 
47
 
 
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);
 
51
                Py_DECREF(zero);
 
52
        }
 
53
 
 
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);
 
56
        Py_DECREF(zero);
 
57
 
 
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);
 
63
                        Py_DECREF(zero);
 
64
                }
 
65
        }
 
66
 
 
67
 
 
68
 
 
69
        PyObject *headers = PyDict_New();
 
70
 
 
71
        for (i = 0; i < wsgi_req->var_cnt; i += 2) {
 
72
#ifdef UWSGI_DEBUG
 
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);
 
74
#endif
 
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);
 
78
#ifdef PYTHREE
 
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);
 
81
#else
 
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);
 
84
#endif
 
85
                        PyObject *old_value = PyDict_GetItem(headers, pydictkey);
 
86
                        if (old_value) {
 
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);
 
92
                                        Py_DECREF(old_value);
 
93
                                }
 
94
                                PyList_Append(old_value, pydictvalue);
 
95
                        }
 
96
                        else {
 
97
                                PyDict_SetItem(headers, pydictkey, pydictvalue);
 
98
                        }
 
99
                        Py_DECREF(pydictkey);
 
100
                        Py_DECREF(pydictvalue);
 
101
                }
 
102
        }
 
103
 
 
104
        PyDict_SetItemString(wsgi_req->async_environ, "headers", headers);
 
105
        Py_DECREF(headers);
 
106
 
 
107
        // if async_post is mapped as a file, directly use it as wsgi.input
 
108
        if (wsgi_req->async_post) {
 
109
#ifdef PYTHREE
 
110
                wsgi_req->async_input = PyFile_FromFd(fileno(wsgi_req->async_post), "pump_body", "rb", 0, NULL, NULL, NULL, 0);
 
111
#else
 
112
                wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "pump_body", "r", NULL);
 
113
#endif
 
114
        }
 
115
        else {
 
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;
 
122
 
 
123
        }
 
124
 
 
125
        PyDict_SetItemString(wsgi_req->async_environ, "body", wsgi_req->async_input);
 
126
 
 
127
 
 
128
        if (wsgi_req->scheme_len > 0) {
 
129
                zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
 
130
        }
 
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");
 
134
                }
 
135
                else {
 
136
                        zero = PyString_FromString("http");
 
137
                }
 
138
        }
 
139
        else {
 
140
                zero = PyString_FromString("http");
 
141
        }
 
142
        PyDict_SetItemString(wsgi_req->async_environ, "scheme", zero);
 
143
        Py_DECREF(zero);
 
144
 
 
145
 
 
146
        wsgi_req->async_app = wi->callable;
 
147
 
 
148
        // export .env only in non-threaded mode
 
149
        if (uwsgi.threads < 2) {
 
150
                PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
 
151
        }
 
152
 
 
153
        PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
 
154
 
 
155
        if (uwsgi.cores > 1) {
 
156
                PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
 
157
        }
 
158
 
 
159
        // cache this ?
 
160
        if (uwsgi.cluster_fd >= 0) {
 
161
                zero = PyString_FromString(uwsgi.cluster);
 
162
                PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
 
163
                Py_DECREF(zero);
 
164
                zero = PyString_FromString(uwsgi.hostname);
 
165
                PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", zero);
 
166
                Py_DECREF(zero);
 
167
        }
 
168
 
 
169
        PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
 
170
 
 
171
 
 
172
        // call
 
173
 
 
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);
 
176
}
 
177
 
 
178
 
 
179
int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
 
180
 
 
181
        PyObject *pychunk;
 
182
        ssize_t wsize;
 
183
        int i;
 
184
 
 
185
        struct http_status_codes *http_sc;
 
186
        char sc[4];
 
187
 
 
188
        UWSGI_GET_GIL
 
189
 
 
190
        // ok its a yield
 
191
        if (!wsgi_req->async_placeholder) {
 
192
                if (PyDict_Check((PyObject *)wsgi_req->async_result)) {
 
193
 
 
194
 
 
195
                        PyObject *status = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "status");
 
196
                        if (!status) {
 
197
                                uwsgi_log("invalid Pump response (status code).\n"); 
 
198
                                goto clear; 
 
199
                        }
 
200
 
 
201
                        PyObject *headers = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "headers");
 
202
                        if (!headers) {
 
203
                                uwsgi_log("invalid Pump response (headers).\n"); 
 
204
                                goto clear; 
 
205
                        }
 
206
 
 
207
 
 
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"); 
 
211
                                goto clear; 
 
212
                        }
 
213
 
 
214
                        // get the status code
 
215
                        if (!PyInt_Check(status)) {
 
216
                                uwsgi_log("invalid Pump response (status code).\n"); 
 
217
                                goto clear; 
 
218
                        }
 
219
 
 
220
                        if (uwsgi_num2str2n(PyInt_AsLong(status), sc, 4) != 3) {
 
221
                                uwsgi_log("invalid Pump response (status code).\n"); 
 
222
                                goto clear; 
 
223
                        }
 
224
 
 
225
                        int found = 0;
 
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;
 
230
                                        found = 1;
 
231
                                        break;
 
232
                                }
 
233
                        }
 
234
                
 
235
                        if (!found) {
 
236
                                uwsgi_log("invalid Pump response (status code).\n"); 
 
237
                                goto clear; 
 
238
                        }
 
239
 
 
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;
 
250
 
 
251
                        UWSGI_RELEASE_GIL
 
252
                        wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 6);
 
253
                        UWSGI_GET_GIL
 
254
                        if (wsize < 0) {
 
255
                                uwsgi_error("writev()");
 
256
                        }
 
257
                        wsgi_req->headers_size += wsize;
 
258
 
 
259
                        PyObject *hhkey, *hhvalue;
 
260
#ifdef UWSGI_PYTHON_OLD
 
261
                        int hhpos = 0;
 
262
#else
 
263
                        Py_ssize_t hhpos = 0;
 
264
#endif
 
265
                        while (PyDict_Next(headers, &hhpos, &hhkey, &hhvalue)) {
 
266
                                if (!PyString_Check(hhkey)) continue;
 
267
 
 
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]);
 
271
 
 
272
                                wsgi_req->hvec[1].iov_base = ": ";
 
273
                                wsgi_req->hvec[1].iov_len = 2;
 
274
 
 
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);
 
283
                                                        UWSGI_RELEASE_GIL
 
284
                                                        wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 4);
 
285
                                                        UWSGI_GET_GIL
 
286
                                                        if (wsize < 0) {
 
287
                                                                uwsgi_error("writev()");
 
288
                                                        }
 
289
                                                        wsgi_req->headers_size += wsize;
 
290
                                                }
 
291
                                        }       
 
292
                                }
 
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);
 
296
                                        UWSGI_RELEASE_GIL
 
297
                                        wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 4);
 
298
                                        UWSGI_GET_GIL
 
299
                                        if (wsize < 0) {
 
300
                                                uwsgi_error("writev()");
 
301
                                        }
 
302
                                        wsgi_req->headers_size += wsize;
 
303
                                }
 
304
                        }
 
305
 
 
306
                        wsgi_req->socket->proto_write(wsgi_req, "\r\n", 2);
 
307
                        Py_INCREF((PyObject *)wsgi_req->async_placeholder);
 
308
 
 
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()");
 
312
                                        goto clear;
 
313
                                }
 
314
                                wsgi_req->response_size += wsize;
 
315
                                goto clear;
 
316
                        }
 
317
#ifdef PYTHREE
 
318
                        else if ((wsgi_req->sendfile_fd = PyObject_AsFileDescriptor((PyObject *)wsgi_req->async_placeholder)) > -1) {
 
319
#else
 
320
                        else if (PyFile_Check((PyObject *)wsgi_req->async_placeholder)) {
 
321
                                wsgi_req->sendfile_fd = fileno(PyFile_AsFile((PyObject *)wsgi_req->async_placeholder));
 
322
#endif
 
323
                                wsize = uwsgi_sendfile(wsgi_req);
 
324
                                if (wsize < 0) {
 
325
                                        goto clear;
 
326
                                }
 
327
                                wsgi_req->response_size += wsize;
 
328
                                goto clear;
 
329
                        }
 
330
 
 
331
                        PyObject *tmp = (PyObject *)wsgi_req->async_placeholder;
 
332
 
 
333
                        wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_placeholder );
 
334
 
 
335
                        Py_DECREF(tmp);
 
336
 
 
337
                        if (!wsgi_req->async_placeholder) {
 
338
                                goto clear;
 
339
                        }
 
340
#ifdef UWSGI_ASYNC
 
341
                        if (uwsgi.async > 1) {
 
342
                                UWSGI_RELEASE_GIL
 
343
                                return UWSGI_AGAIN;
 
344
                        }
 
345
#endif
 
346
                }
 
347
                else {
 
348
                        uwsgi_log("invalid Pump response.\n"); 
 
349
                        goto clear; 
 
350
                }
 
351
        }
 
352
 
 
353
 
 
354
 
 
355
        pychunk = PyIter_Next(wsgi_req->async_placeholder);
 
356
 
 
357
        if (!pychunk) {
 
358
                if (PyErr_Occurred()) PyErr_Print();
 
359
                goto clear;
 
360
        }
 
361
 
 
362
 
 
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()");
 
366
                        Py_DECREF(pychunk);
 
367
                        goto clear;
 
368
                }
 
369
                wsgi_req->response_size += wsize;
 
370
        }
 
371
 
 
372
 
 
373
        Py_DECREF(pychunk);
 
374
        UWSGI_RELEASE_GIL
 
375
        return UWSGI_AGAIN;
 
376
 
 
377
clear:
 
378
        if (wsgi_req->async_input) {
 
379
                Py_DECREF((PyObject *)wsgi_req->async_input);
 
380
        }
 
381
        if (wsgi_req->async_environ) {
 
382
                PyDict_Clear(wsgi_req->async_environ);
 
383
        }
 
384
        Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
 
385
 
 
386
        Py_DECREF((PyObject *)wsgi_req->async_result);
 
387
        PyErr_Clear();
 
388
 
 
389
        UWSGI_RELEASE_GIL
 
390
        return UWSGI_OK;
 
391
}
 
392