prepare for new routing system

This commit is contained in:
roberto@goyle
2012-02-02 18:20:10 +01:00
parent 97a8c5e4b6
commit a92c2003ee
8 changed files with 17 additions and 267 deletions
+1
View File
@@ -18,6 +18,7 @@ async = true
evdis = false
ldap = auto
pcre = auto
routing = true
debug = false
unbit = false
xml_implementation = libxml2
-10
View File
@@ -156,18 +156,8 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
#ifdef UWSGI_ROUTING
uwsgi_log("routing %d routes %d\n", uwsgi.routing, uwsgi.nroutes);
if (uwsgi.routing && uwsgi.nroutes > 0) {
check_route(uwsgi, wsgi_req);
}
#endif
// call
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
return python_call(wsgi_req->async_app, wsgi_req->async_args, up.catch_exceptions, wsgi_req);
}
+2 -143
View File
@@ -1,148 +1,7 @@
#ifdef UWSGI_ROUTING
#include "uwsgi.h"
void routing_setup(struct uwsgi_server *uwsgi) {
int i;
struct uwsgi_route *ur;
int max_ovec = 0;
for(i=0;i<uwsgi->nroutes;i++) {
uwsgi_log("%d = %p\n", i, uwsgi->routes[i].pattern);
ur = &uwsgi->routes[i];
if (ur->args > max_ovec) {
max_ovec = ur->args;
}
}
uwsgi->async_ovector = malloc( sizeof(int *) * uwsgi->async);
if (!uwsgi->async_ovector) {
uwsgi_error("malloc()");
exit(1);
}
uwsgi_log("max_ovec = %d\n", max_ovec);
for(i=0;i<uwsgi->async;i++) {
uwsgi->async_ovector[i] = malloc(sizeof(int) * ((max_ovec+1)*3));
if (!uwsgi->async_ovector[i]) {
uwsgi_error("malloc()");
exit(1);
}
}
int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
return 0;
}
void check_route(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int ret,i;
struct uwsgi_route *ur;
for(i=0;i<uwsgi->nroutes;i++) {
//uwsgi_log("checking route %d\n", i);
ur = &uwsgi->routes[i];
ret = pcre_exec(ur->pattern, ur->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len, 0, 0, wsgi_req->ovector, (ur->args+1)*3 );
if (ret >= 0) {
uwsgi_log("found route %d for PATH_INFO=%.*s\n", i, wsgi_req->path_info_len, wsgi_req->path_info);
if (ur->action) {
ur->action(uwsgi, wsgi_req, ur);
}
else {
uwsgi_route_action_wsgi(uwsgi, wsgi_req, ur);
}
}
/* TODO check for errors if < 0 && != NO_MATCH */
}
return;
}
void uwsgi_route_action_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
int i;
PyObject *route_py_callbase, *route_py_dict = NULL;
uwsgi_log("managing WSGI route...\n");
if (ur->callable == NULL) {
if (ur->callbase) {
route_py_callbase = PyImport_ImportModule(ur->callbase);
if (route_py_callbase == NULL) {
PyErr_Print();
}
else {
uwsgi_log("callbase dict ok for %s\n", ur->call);
route_py_dict = PyModule_GetDict(route_py_callbase);
}
}
ur->callable = PyDict_GetItemString(route_py_dict, ur->call);
if (ur->callable == NULL) {
uwsgi_log("route_py_dict: %p call: %s\n", route_py_dict, ur->call);
PyErr_Print();
}
}
// TODO put regex captured groups in WSGI env
PyObject *ra = PyTuple_New(ur->args);
for (i=1;i<=ur->args;i++) {
PyTuple_SetItem(ra, i-1, PyString_FromStringAndSize(
wsgi_req->path_info + wsgi_req->ovector[i*2],
wsgi_req->ovector[(i*2)+1] - wsgi_req->ovector[i*2]
));
}
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.uwsgi.route_args", ra);
if (ur->callable) {
wsgi_req->async_app = ur->callable;
}
}
void uwsgi_route_action_uwsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
PyObject *route_py_callbase, *route_py_dict = NULL;
int i;
uwsgi_log("managing uwsgi route...\n");
if (ur->callable == NULL) {
if (ur->callbase) {
route_py_callbase = PyImport_ImportModule(ur->callbase);
if (route_py_callbase == NULL) {
PyErr_Print();
}
else {
uwsgi_log("callbase dict ok for %s\n", ur->call);
route_py_dict = PyModule_GetDict(route_py_callbase);
}
}
ur->callable = PyDict_GetItemString(route_py_dict, ur->call);
if (ur->callable == NULL) {
uwsgi_log("route_py_dict: %p call: %s\n", route_py_dict, ur->call);
PyErr_Print();
}
ur->callable_args = PyTuple_New(ur->args+1);
}
if (ur->callable) {
uwsgi_log("route callable dict ok: %d\n", ur->args);
wsgi_req->async_app = ur->callable;
wsgi_req->async_args = ur->callable_args;
for (i=1;i<=ur->args;i++) {
uwsgi_log("%d\n", i);
uwsgi_log("%d / %d\n", wsgi_req->ovector[i*2], wsgi_req->ovector[(i*2)+1]);
uwsgi_log("%d = %.*s\n", i,wsgi_req->ovector[(i*2)+1] - wsgi_req->ovector[i*2],
wsgi_req->path_info + wsgi_req->ovector[i*2]);
PyTuple_SetItem(wsgi_req->async_args, i, PyString_FromStringAndSize(
wsgi_req->path_info + wsgi_req->ovector[i*2],
wsgi_req->ovector[(i*2)+1] - wsgi_req->ovector[i*2]
));
}
uwsgi_log("route callable built\n");
}
}
#endif
+4 -4
View File
@@ -852,10 +852,6 @@ void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id, struct uwsgi_so
wsgi_req->hvec = uwsgi.async_hvec[wsgi_req->async_id];
wsgi_req->buffer = uwsgi.async_buf[wsgi_req->async_id];
#ifdef UWSGI_ROUTING
wsgi_req->ovector = uwsgi.async_ovector[wsgi_req->async_id];
#endif
if (uwsgi.post_buffering > 0) {
wsgi_req->post_buffering_buf = uwsgi.async_post_buf[wsgi_req->async_id];
}
@@ -923,6 +919,10 @@ int wsgi_req_recv(struct wsgi_request *wsgi_req) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
#ifdef UWSGI_ROUTING
if (uwsgi_apply_routes(wsgi_req)) return 0;
#endif
wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);
return 0;
-4
View File
@@ -2479,10 +2479,6 @@ skipzero:
}
#endif
#ifdef UWSGI_ROUTING
routing_setup();
#endif
if (!uwsgi.master_process) {
if (uwsgi.numproc == 1) {
uwsgi_log("spawned uWSGI worker 1 (and the only) (pid: %d, cores: %d)\n", masterpid, uwsgi.cores);
+6 -27
View File
@@ -669,24 +669,9 @@ struct uwsgi_spooler {
#ifdef UWSGI_ROUTING
struct uwsgi_route {
const char *mountpoint;
const char *callbase;
uint8_t modifier1;
uint8_t modifier2;
pcre *pattern;
pcre_extra *pattern_extra;
pcre *method;
pcre_extra *method_extra;
const char *call;
int modifier1;
int modifier2;
void *callable;
void *callable_args;
int args;
void (*action) (struct wsgi_request *, struct uwsgi_route *);
};
#endif
@@ -1162,10 +1147,6 @@ struct uwsgi_server {
struct wsgi_request **async_queue_unused;
#ifdef UWSGI_ROUTING
int **async_ovector;
#endif
// store rlimit
struct rlimit rl;
size_t limit_post;
@@ -1308,12 +1289,7 @@ struct uwsgi_server {
#ifdef UWSGI_ROUTING
#ifndef MAX_UWSGI_ROUTES
#define MAX_UWSGI_ROUTES 64
#endif
int routing;
int nroutes;
struct uwsgi_route routes[MAX_UWSGI_ROUTES];
struct uwsgi_route *routes;
#endif
int single_interpreter;
@@ -2556,6 +2532,9 @@ void uwsgi_opt_set_unshare(char *, char *, void *);
char *uwsgi_tmpname(char *, char *);
#ifdef UWSGI_ROUTING
int uwsgi_apply_routes(struct wsgi_request *);
#endif
#ifdef UWSGI_AS_SHARED_LIBRARY
int uwsgi_init(int, char **, char **);
+4
View File
@@ -513,6 +513,10 @@ class uConf(object):
if self.get('udp'):
self.cflags.append("-DUWSGI_UDP")
if self.get('routing'):
self.gcc_list.append('routing')
self.cflags.append("-DUWSGI_ROUTING")
# re-enable after pcre fix
if self.get('pcre'):
if self.get('pcre') == 'auto':
-79
View File
@@ -100,17 +100,6 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, int app_tag
continue;
}
#ifdef UWSGI_ROUTING
if (!strcmp((char *) node->name, "route")) {
uwsgi.xml_round2 = 1;
continue;
}
if (!strcmp((char *) node->name, "routing")) {
uwsgi.xml_round2 = 1;
continue;
}
#endif
node_mode = xmlGetProp(node, (const xmlChar *) "mode");
if (uwsgi.mode && node_mode) {
if (strcmp(uwsgi.mode, (char *) node_mode)) {
@@ -170,81 +159,13 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, int app_tag
}
}
}
#ifdef UWSGI_ROUTING
else if (!strcmp((char *) node->name, "routing")) {
unsigned char *default_route_mountpoint = NULL;
unsigned char *default_route_callbase = NULL;
xmlChar *tmp_val;
int default_route_modifier1 = 0;
int default_route_modifier2 = 0;
const char *errstr;
int erroff;
default_route_mountpoint = xmlGetProp(node, (const xmlChar *) "mountpoint");
default_route_callbase = xmlGetProp(node, (const xmlChar *) "base");
tmp_val = xmlGetProp(node, (const xmlChar *) "modifier1");
if (tmp_val) {
default_route_modifier1 = atoi( (char *)tmp_val);
}
tmp_val = xmlGetProp(node, (const xmlChar *) "modifier2");
if (tmp_val) {
default_route_modifier2 = atoi( (char *) tmp_val);
}
for (node2 = node->children; node2; node2 = node2->next) {
if (node2->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node2->name, "route") && uwsgi.nroutes < MAX_UWSGI_ROUTES) {
if (!node2->children) {
uwsgi_log( "no route callable defined. skip.\n");
continue;
}
uwsgi.routes[uwsgi.nroutes].mountpoint = (char *) default_route_mountpoint;
uwsgi.routes[uwsgi.nroutes].callbase = (char *) default_route_callbase;
uwsgi.routes[uwsgi.nroutes].modifier1 = default_route_modifier1;
uwsgi.routes[uwsgi.nroutes].modifier2 = default_route_modifier2;
// TODO check for action
uwsgi.routes[uwsgi.nroutes].action = NULL;
uwsgi.routes[uwsgi.nroutes].call = (char *) node2->children->content;
if (uwsgi.routes[uwsgi.nroutes].call == NULL) {
uwsgi_log( "no route callable defined. skip.\n");
continue;
}
tmp_val = xmlGetProp(node2, (const xmlChar *) "pattern");
if (!tmp_val) {
uwsgi_log( "no route pattern defined. skip.\n");
continue;
}
uwsgi.routes[uwsgi.nroutes].pattern = pcre_compile( (char *) tmp_val, 0, &errstr, &erroff, NULL);
uwsgi.routes[uwsgi.nroutes].pattern_extra = pcre_study(uwsgi.routes[uwsgi.nroutes].pattern, 0, &errstr);
pcre_fullinfo(uwsgi.routes[uwsgi.nroutes].pattern, uwsgi.routes[uwsgi.nroutes].pattern_extra, PCRE_INFO_CAPTURECOUNT, &uwsgi.routes[uwsgi.nroutes].args);
uwsgi_log("route call: %s %d\n", uwsgi.routes[uwsgi.nroutes].call, uwsgi.routes[uwsgi.nroutes].args);
uwsgi.nroutes++;
}
}
}
}
#endif
}
}
}
/* We cannot free xml resources on the first round (and with routing enabled) as the string pointer must be valid for all the server lifecycle */
#ifdef UWSGI_ROUTING
if (app_tag && !uwsgi.routing) {
#else
if (app_tag) {
#endif
xmlFreeDoc (doc);
xmlCleanupParser ();
}