mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-05 05:01:36 +00:00
prepare for new routing system
This commit is contained in:
@@ -18,6 +18,7 @@ async = true
|
||||
evdis = false
|
||||
ldap = auto
|
||||
pcre = auto
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 **);
|
||||
|
||||
@@ -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':
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user