added uwsgi.fcgi() api function to allows uWSGI being a fastcgi proxy/router

This commit is contained in:
roberto@maverick64
2011-01-23 14:35:42 +01:00
parent 9ac598b9c3
commit 9cbf1c545d
3 changed files with 255 additions and 2 deletions
+121 -2
View File
@@ -1378,7 +1378,9 @@ clear:
return Py_None;
}
typedef struct {
struct uwsgi_Iter;
typedef struct uwsgi_Iter{
PyObject_HEAD
int fd;
int timeout;
@@ -1389,6 +1391,7 @@ typedef struct {
uint16_t sent;
uint8_t modifier1;
uint8_t modifier2;
PyObject* (*func)(struct uwsgi_Iter *);
} uwsgi_Iter;
@@ -1397,6 +1400,19 @@ PyObject* uwsgi_Iter_iter(PyObject *self) {
return self;
}
PyObject* py_fcgi_iterator(uwsgi_Iter *ui) {
uint16_t size = 0;
char body[0xffff];
size = fcgi_get_record(ui->fd, body);
if (size) {
return PyString_FromStringAndSize(body, size);
}
return NULL;
}
PyObject* uwsgi_Iter_next(PyObject *self) {
int rlen;
uwsgi_Iter *ui = (uwsgi_Iter *)self;
@@ -1404,9 +1420,20 @@ PyObject* uwsgi_Iter_next(PyObject *self) {
int i = 4;
struct uwsgi_header uh;
char *ub = (char *) &uh ;
PyObject *ptr;
UWSGI_RELEASE_GIL
uwsgi_log("waiting for data\n");
if (ui->func) {
ptr = ui->func(ui);
if (ptr) {
return ptr;
}
}
else {
if (!ui->started) {
memset(&uh, 0, 4);
@@ -1466,6 +1493,7 @@ PyObject* uwsgi_Iter_next(PyObject *self) {
else if (rlen == 0) {
uwsgi_log("uwsgi request timed out waiting for response\n");
}
}
if (ui->close) {
close(ui->fd);
@@ -1589,6 +1617,94 @@ clear:
}
PyObject *py_uwsgi_fcgi(PyObject * self, PyObject * args) {
char *node;
PyObject *dict;
int fd;
int i;
int stdin_fd = -1;
int stdin_size = 0;
ssize_t len;
char stdin_buf[0xffff];
uwsgi_Iter *ui;
PyObject *zero, *key, *val;
if (!PyArg_ParseTuple(args, "sO|ii:fcgi", &node, &dict, &stdin_fd, &stdin_size)) {
return NULL;
}
fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) goto clear2;
if (!PyDict_Check(dict)) goto clear;
fcgi_send_record(fd, 1, 8, FCGI_BEGIN_REQUEST);
PyObject *vars = PyDict_Items(dict);
if (!vars) goto clear;
for (i = 0; i < PyList_Size(vars); i++) {
zero = PyList_GetItem(vars, i);
if (!zero) {
PyErr_Print();
continue;
}
key = PyTuple_GetItem(zero, 0);
val = PyTuple_GetItem(zero, 1);
if (!PyString_Check(key) || !PyString_Check(val)) continue;
fcgi_send_param(fd,
PyString_AsString(key), PyString_Size(key),
PyString_AsString(val), PyString_Size(val));
}
fcgi_send_record(fd, 4, 0, "");
if (stdin_fd > -1 && stdin_size) {
while(stdin_size) {
len = read(stdin_fd, stdin_buf, UMIN(0xffff, stdin_size));
if (len < 0) {
uwsgi_error("read()");
break;
}
fcgi_send_record(fd, 5, len, stdin_buf);
stdin_size-=len;
}
}
fcgi_send_record(fd, 5, 0, "");
// request sent, return the iterator response
ui = PyObject_New(uwsgi_Iter, &uwsgi_IterType);
if (!ui) {
PyErr_Print();
goto clear;
}
ui->fd = fd;
ui->timeout = -1;
ui->close = 1;
ui->started = 0;
ui->has_cl = 0;
ui->sent = 0;
ui->size = 0;
ui->func = py_fcgi_iterator;
return (PyObject *) ui;
clear:
close(fd);
clear2:
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_send_message(PyObject * self, PyObject * args) {
PyObject *destination = NULL, *pyobj = NULL, *marshalled = NULL;
@@ -1668,6 +1784,7 @@ PyObject *py_uwsgi_send_message(PyObject * self, PyObject * args) {
ui->has_cl = 0;
ui->sent = 0;
ui->size = 0;
ui->func = NULL;
return (PyObject *) ui;
@@ -2175,6 +2292,8 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"recv_block", py_uwsgi_recv_block, METH_VARARGS, ""},
{"recv_frame", py_uwsgi_recv_frame, METH_VARARGS, ""},
{"close", py_uwsgi_close, METH_VARARGS, ""},
{"fcgi", py_uwsgi_fcgi, METH_VARARGS, ""},
{"parsefile", py_uwsgi_parse_file, METH_VARARGS, ""},
//{"call_hook", py_uwsgi_call_hook, METH_VARARGS, ""},