From 0c26928236347e4e1dd7da8a13aa2c3e17be6fd4 Mon Sep 17 00:00:00 2001 From: Unbit Date: Mon, 25 Mar 2013 09:56:53 +0100 Subject: [PATCH] added cookie management and --route-run --- core/cookie.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ core/routing.c | 35 ++++++++++++++++++---- core/uwsgi.c | 1 + uwsgi.h | 2 ++ uwsgiconfig.py | 2 +- 5 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 core/cookie.c diff --git a/core/cookie.c b/core/cookie.c new file mode 100644 index 00000000..37350bf0 --- /dev/null +++ b/core/cookie.c @@ -0,0 +1,81 @@ +#include + +/* + + cookie management functions (mainly used by the internal routing subsystem) + +*/ + +static char *check_cookie(char *cookie, uint16_t cookie_len, char *key, uint16_t keylen, uint16_t *vallen) { + uint16_t orig_cookie_len = cookie_len-1; + // first lstrip white spaces + char *ptr = cookie; + uint16_t i; + for(i=0;i0;i--) { + if (isspace((int)ptr[i])) { + cookie_len--; + } + else { + break; + } + } + + // now search for the first equal sign + char *equal = memchr(cookie, '=', cookie_len); + if (!equal) return NULL; + + if (uwsgi_strncmp(key, keylen, cookie, equal-cookie)) { + return NULL; + } + + cookie_len -= (equal-cookie)+1; + if (cookie_len == 0) return NULL; + + *vallen = cookie_len; + return equal+1; +} + +char *uwsgi_get_cookie(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) { + uint16_t i; + + char *cookie = wsgi_req->cookie; + uint16_t cookie_len = 0; + char *ptr = wsgi_req->cookie; + //start splitting by ; + for(i=0;icookie_len;i++) { + if (!cookie) { + cookie = ptr + i; + } + if (ptr[i] == ';') { + char *value = check_cookie(cookie, cookie_len, key, keylen, vallen); + if (value) { + return value; + } + cookie_len = 0; + cookie = NULL; + } + else { + cookie_len++; + } + } + + if (cookie_len > 0) { + char *value = check_cookie(cookie, cookie_len, key, keylen, vallen); + if (value) { + return value; + } + } + + return NULL; +} diff --git a/core/routing.c b/core/routing.c index 4cb82c66..ec6cd423 100644 --- a/core/routing.c +++ b/core/routing.c @@ -44,9 +44,17 @@ struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, stru case 2: if (pass1[i] == '}') { uint16_t vallen = 0; - char *value = uwsgi_get_var(wsgi_req, key, keylen, &vallen); - if (value) { - if (uwsgi_buffer_append(ub, value, vallen)) goto error; + if (!uwsgi_starts_with(key, keylen, "cookie[", 7) && keylen > 0 && key[keylen-1] == ']') { + char *value = uwsgi_get_cookie(wsgi_req, key + 7, keylen -8, &vallen); + if (value) { + if (uwsgi_buffer_append(ub, value, vallen)) goto error; + } + } + else { + char *value = uwsgi_get_var(wsgi_req, key, keylen, &vallen); + if (value) { + if (uwsgi_buffer_append(ub, value, vallen)) goto error; + } } status = 0; key = NULL; @@ -108,6 +116,11 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t wsgi_req->route_goto = 0; if (!routes->if_func) { + // could be a "run" + if (!routes->subject) { + n = 0; + goto run; + } if (!subject) { char **subject2 = (char **) (((char *) (wsgi_req)) + routes->subject); uint16_t *subject_len2 = (uint16_t *) (((char *) (wsgi_req)) + routes->subject_len); @@ -137,6 +150,7 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t } } +run: if (n >= 0) { wsgi_req->is_routing = 1; int ret = routes->func(wsgi_req, routes); @@ -197,6 +211,8 @@ static void *uwsgi_route_get_condition_func(char *name) { void uwsgi_opt_add_route(char *opt, char *value, void *foobar) { + char *space = NULL; + char *command = NULL; struct uwsgi_route *old_ur = NULL,*ur = uwsgi.routes; uint64_t pos = 0; while(ur) { @@ -223,7 +239,12 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) { char *route = uwsgi_str(value); - char *space = strchr(route, ' '); + if (!strcmp(foobar, "run")) { + command = route; + goto done; + } + + space = strchr(route, ' '); if (!space) { uwsgi_log("invalid route syntax\n"); exit(1); @@ -299,7 +320,8 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) { } } - char *command = space + 1; + command = space + 1; +done: ur->action = uwsgi_str(command); char *colon = strchr(command, ':'); @@ -880,6 +902,9 @@ void uwsgi_routing_dump() { if (routes->label) { uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label); } + else if (!routes->subject_str && !routes->if_func) { + uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action); + } else { uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action); } diff --git a/core/uwsgi.c b/core/uwsgi.c index 72f6befa..665103d6 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -513,6 +513,7 @@ static struct uwsgi_option uwsgi_base_options[] = { {"route-label", required_argument, 0, "add a routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0}, {"route-if", required_argument, 0, "add a route based on condition", uwsgi_opt_add_route, "if", 0}, {"route-if-not", required_argument, 0, "add a route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0}, + {"route-run", required_argument, 0, "always run the specified route action", uwsgi_opt_add_route, "run", 0}, {"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0}, {"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0}, #endif diff --git a/uwsgi.h b/uwsgi.h index 083fb204..366d5ad0 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -3912,6 +3912,8 @@ char *uwsgi_deflate(z_stream *, char *, size_t, size_t *); void uwsgi_crc32(uint32_t *, char *, size_t); #endif +char *uwsgi_get_cookie(struct wsgi_request *, char *, uint16_t, uint16_t *); + void uwsgi_check_emperor(void); #ifdef UWSGI_AS_SHARED_LIBRARY int uwsgi_init(int, char **, char **); diff --git a/uwsgiconfig.py b/uwsgiconfig.py index b0768f7a..0f3ec963 100644 --- a/uwsgiconfig.py +++ b/uwsgiconfig.py @@ -461,7 +461,7 @@ class uConf(object): 'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm', 'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events', 'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini', - 'core/rpc', 'core/gateway', 'core/loop', 'core/rb_timers', 'core/uwsgi'] + 'core/rpc', 'core/gateway', 'core/loop', 'core/cookie', 'core/rb_timers', 'core/uwsgi'] # add protocols self.gcc_list.append('proto/base') self.gcc_list.append('proto/uwsgi')