From 736f99d10ba7e1f6a22a1fd405ed9666fa791fc0 Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Mon, 29 Oct 2012 10:11:42 +0100 Subject: [PATCH] added router_cache plugin --- buildconf/base.ini | 2 +- plugins/router_access/router_access.c | 6 +- plugins/router_cache/router_cache.c | 108 ++++++++++++++++++++++++++ plugins/router_cache/uwsgiplugin.py | 6 ++ 4 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 plugins/router_cache/router_cache.c create mode 100644 plugins/router_cache/uwsgiplugin.py diff --git a/buildconf/base.ini b/buildconf/base.ini index a34ed0a8..d7cdc164 100644 --- a/buildconf/base.ini +++ b/buildconf/base.ini @@ -29,7 +29,7 @@ plugins = bin_name = uwsgi append_version = plugin_dir = . -embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile +embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache as_shared_library = false locking = auto diff --git a/plugins/router_access/router_access.c b/plugins/router_access/router_access.c index a228e8c6..f465691f 100644 --- a/plugins/router_access/router_access.c +++ b/plugins/router_access/router_access.c @@ -22,7 +22,7 @@ struct uwsgi_router_access_conf { char *addr; }; -int uwsgi_routing_func_access(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){ +static int uwsgi_routing_func_access(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){ int pass = 0; struct uwsgi_router_access_conf *urac = (struct uwsgi_router_access_conf *) ur->data2; @@ -65,14 +65,14 @@ forbidden: return UWSGI_ROUTE_BREAK; } -int uwsgi_router_access(struct uwsgi_route *ur, char *args) { +static int uwsgi_router_access(struct uwsgi_route *ur, char *args) { ur->func = uwsgi_routing_func_access; ur->data = args; ur->data_len = strlen(args); return 0; } -void router_access_register() { +static void router_access_register() { uwsgi_register_router("access", uwsgi_router_access); } diff --git a/plugins/router_cache/router_cache.c b/plugins/router_cache/router_cache.c new file mode 100644 index 00000000..7255722f --- /dev/null +++ b/plugins/router_cache/router_cache.c @@ -0,0 +1,108 @@ +#include "../../uwsgi.h" + +extern struct uwsgi_server uwsgi; + +/* + + by Unbit + + syntax: + + route = /^foobar1 cache:key=PATH_INFO,type=body + route = /^foobar2 cache:key=REQUEST_URI,type=full + route = /^foobar3 cache:key=REQUEST_URI,type=body,content_type=text/html + +*/ + +struct uwsgi_router_cache_conf { + char *key; + char *type; + + long key_offset; + long key_offset_len; + + char *content_type; + size_t content_type_len; + + // 0 -> full, 1 -> body + int type_num; + +}; + +static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){ + + struct uwsgi_router_cache_conf *urcc = (struct uwsgi_router_cache_conf *) ur->data2; + + if (!uwsgi.cache_max_items) return UWSGI_ROUTE_NEXT; + + if (!urcc) { + urcc = uwsgi_calloc(sizeof(struct uwsgi_router_cache_conf)); + if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=', + "key", &urcc->key, + "content_type", &urcc->content_type, + "type", &urcc->type, NULL)) { + free(urcc); + return UWSGI_ROUTE_NEXT; + } + if (!urcc->key) urcc->key = "REQUEST_URI"; + if (!urcc->type) urcc->type = "full"; + if (!urcc->content_type) urcc->content_type = "text/html"; + + urcc->content_type_len = strlen(urcc->content_type); + + if (!strcmp(urcc->key, "REQUEST_URI")) { + urcc->key_offset = offsetof(struct wsgi_request, uri); + urcc->key_offset_len = offsetof(struct wsgi_request, uri_len); + } + else if (!strcmp(urcc->key, "PATH_INFO")) { + urcc->key_offset = offsetof(struct wsgi_request, path_info); + urcc->key_offset_len = offsetof(struct wsgi_request, path_info_len); + } + else { + urcc->key_offset = offsetof(struct wsgi_request, uri); + urcc->key_offset_len = offsetof(struct wsgi_request, uri_len); + } + + if (!strcmp(urcc->type, "body")) { + urcc->type_num = 1; + } + + ur->data2 = urcc; + } + + char **key = (char **) (((char *) wsgi_req) + urcc->key_offset); + uint16_t *keylen = (uint16_t *) (((char *) wsgi_req) + urcc->key_offset_len); + + uint64_t valsize = 0; + char *value = uwsgi_cache_get(*key, *keylen, &valsize); + if (value) { + // body only + if (urcc->type_num == 1) { + wsgi_req->status = 200; + wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type: ", 50); + wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, urcc->content_type, urcc->content_type_len); + wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n\r\n", 4); + wsgi_req->header_cnt = 2; + } + wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, value, valsize); + return UWSGI_ROUTE_BREAK; + } + + return UWSGI_ROUTE_NEXT; +} + +static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) { + ur->func = uwsgi_routing_func_cache; + ur->data = args; + ur->data_len = strlen(args); + return 0; +} + +static void router_cache_register() { + uwsgi_register_router("cache", uwsgi_router_cache); +} + +struct uwsgi_plugin router_cache_plugin = { + .name = "router_cache", + .on_load = router_cache_register, +}; diff --git a/plugins/router_cache/uwsgiplugin.py b/plugins/router_cache/uwsgiplugin.py new file mode 100644 index 00000000..4bad3f5f --- /dev/null +++ b/plugins/router_cache/uwsgiplugin.py @@ -0,0 +1,6 @@ +NAME='router_cache' + +CFLAGS = [] +LDFLAGS = [] +LIBS = [] +GCC_LIST = ['router_cache']