From 2a2c650becd645bd36584a9cc1a4468f54543f59 Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Thu, 3 Jan 2013 10:13:38 +0100 Subject: [PATCH] improved routing subsystem with the GOON return code --- core/routing.c | 51 ++++++++++++++++++--- core/uwsgi.c | 7 +++ plugins/router_basicauth/router_basicauth.c | 17 +++++-- uwsgi.h | 8 ++++ 4 files changed, 73 insertions(+), 10 deletions(-) diff --git a/core/routing.c b/core/routing.c index 3b907dc8..493d7207 100644 --- a/core/routing.c +++ b/core/routing.c @@ -6,6 +6,7 @@ extern struct uwsgi_server uwsgi; int uwsgi_apply_routes(struct wsgi_request *wsgi_req) { struct uwsgi_route *routes = uwsgi.routes; + void *goon_func = NULL; if (!routes) return UWSGI_ROUTE_CONTINUE; @@ -15,6 +16,10 @@ int uwsgi_apply_routes(struct wsgi_request *wsgi_req) { } while (routes) { + if (goon_func && goon_func == routes->func) { + goto next; + } + goon_func = NULL; char **subject = (char **) (((char *) (wsgi_req)) + routes->subject); uint16_t *subject_len = (uint16_t *) (((char *) (wsgi_req)) + routes->subject_len); #ifdef UWSGI_DEBUG @@ -23,11 +28,19 @@ int uwsgi_apply_routes(struct wsgi_request *wsgi_req) { int n = uwsgi_regexp_match_ovec(routes->pattern, routes->pattern_extra, *subject, *subject_len, routes->ovector, routes->ovn); if (n >= 0) { int ret = routes->func(wsgi_req, routes); - if (ret == UWSGI_ROUTE_BREAK) uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].routed_requests++; - if (ret != UWSGI_ROUTE_NEXT) { + if (ret == UWSGI_ROUTE_BREAK) { + uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].routed_requests++; return ret; } + if (ret == UWSGI_ROUTE_CONTINUE) { + return ret; + } + + if (ret == UWSGI_ROUTE_GOON) { + goon_func = routes->func; + } } +next: routes = routes->next; } @@ -36,21 +49,33 @@ int uwsgi_apply_routes(struct wsgi_request *wsgi_req) { int uwsgi_apply_routes_fast(struct wsgi_request *wsgi_req, char *uri, int len) { + void *goon_func = NULL; + struct uwsgi_route *routes = uwsgi.routes; if (!routes) return UWSGI_ROUTE_CONTINUE; while (routes) { + if (goon_func && goon_func == routes->func) { + goto next; + } + goon_func = NULL; int n = uwsgi_regexp_match_ovec(routes->pattern, routes->pattern_extra, uri, len, routes->ovector, routes->ovn); if (n >= 0) { int ret = routes->func(wsgi_req, routes); - if (ret == UWSGI_ROUTE_BREAK) uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].routed_requests++; - if (ret != UWSGI_ROUTE_NEXT) { - return ret; - } + if (ret == UWSGI_ROUTE_BREAK) { + uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].routed_requests++; + return ret; + } + if (ret == UWSGI_ROUTE_CONTINUE) { + return ret; + } + if (ret == UWSGI_ROUTE_GOON) { + goon_func = routes->func; + } } - +next: routes = routes->next; } @@ -146,6 +171,18 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) { exit(1); } +int uwsgi_router_continue(struct uwsgi_route *ur, char *arg) { + return UWSGI_ROUTE_CONTINUE; +} + +int uwsgi_router_break(struct uwsgi_route *ur, char *arg) { + return UWSGI_ROUTE_BREAK; +} + +int uwsgi_router_goon(struct uwsgi_route *ur, char *arg) { + return UWSGI_ROUTE_GOON; +} + struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) { struct uwsgi_router *ur = uwsgi.routers; diff --git a/core/uwsgi.c b/core/uwsgi.c index de76bf66..36ce1e19 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -1871,6 +1871,13 @@ int main(int argc, char *argv[], char *envp[]) { uwsgi_register_loop("async", async_loop); #endif +#ifdef UWSGI_ROUTING + uwsgi_register_router("continue", uwsgi_router_continue); + uwsgi_register_router("last", uwsgi_router_continue); + uwsgi_register_router("break", uwsgi_router_break); + uwsgi_register_router("goon", uwsgi_router_goon); +#endif + // setup cheaper algos uwsgi_register_cheaper_algo("spare", uwsgi_cheaper_algo_spare); uwsgi_register_cheaper_algo("backlog", uwsgi_cheaper_algo_backlog); diff --git a/plugins/router_basicauth/router_basicauth.c b/plugins/router_basicauth/router_basicauth.c index 655c5f3e..255089bf 100644 --- a/plugins/router_basicauth/router_basicauth.c +++ b/plugins/router_basicauth/router_basicauth.c @@ -153,7 +153,9 @@ int uwsgi_routing_func_basicauth(struct wsgi_request *wsgi_req, struct uwsgi_rou if (wsgi_req->remote_user) wsgi_req->remote_user_len = ulen; free(auth); - return UWSGI_ROUTE_CONTINUE; + if (ur->data3_len > 0) + return UWSGI_ROUTE_CONTINUE; + return UWSGI_ROUTE_GOON; } } else { @@ -162,7 +164,9 @@ int uwsgi_routing_func_basicauth(struct wsgi_request *wsgi_req, struct uwsgi_rou if (wsgi_req->remote_user) wsgi_req->remote_user_len = ur->custom; free(auth); - return UWSGI_ROUTE_CONTINUE; + if (ur->data3_len > 0) + return UWSGI_ROUTE_CONTINUE; + return UWSGI_ROUTE_GOON; } } free(auth); @@ -197,7 +201,7 @@ void router_basicauth_init_lock() { } #endif -int uwsgi_router_basicauth(struct uwsgi_route *ur, char *args) { +static int uwsgi_router_basicauth(struct uwsgi_route *ur, char *args) { ur->func = uwsgi_routing_func_basicauth; @@ -227,10 +231,17 @@ int uwsgi_router_basicauth(struct uwsgi_route *ur, char *args) { return 0; } +static int uwsgi_router_basicauth_last(struct uwsgi_route *ur, char *args) { + uwsgi_router_basicauth(ur, args); + ur->data3_len = 1; + return 0; +} + void router_basicauth_register(void) { uwsgi_register_router("basicauth", uwsgi_router_basicauth); + uwsgi_register_router("basicauth-last", uwsgi_router_basicauth_last); } struct uwsgi_plugin router_basicauth_plugin = { diff --git a/uwsgi.h b/uwsgi.h index 6790d57a..0ca7ac4d 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -907,9 +907,14 @@ struct uwsgi_spooler { #ifdef UWSGI_ROUTING +// go to the next route #define UWSGI_ROUTE_NEXT 0 +// continue to the request handler #define UWSGI_ROUTE_CONTINUE 1 +// close the request #define UWSGI_ROUTE_BREAK 2 +// go to the next group of routes +#define UWSGI_ROUTE_GOON 3 struct uwsgi_route { @@ -3227,6 +3232,9 @@ struct uwsgi_router *uwsgi_register_router(char *, int (*)(struct uwsgi_route *, void uwsgi_opt_add_route(char *, char *, void *); int uwsgi_apply_routes(struct wsgi_request *); int uwsgi_apply_routes_fast(struct wsgi_request *, char *, int); +int uwsgi_router_continue(struct uwsgi_route *, char *); +int uwsgi_router_break(struct uwsgi_route *, char *); +int uwsgi_router_goon(struct uwsgi_route *, char *); #endif void uwsgi_reload(char **);