mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-08-29 20:54:04 +00:00
c595844f0e
Reported by Coverity as CID #995792.
195 lines
5.4 KiB
C
195 lines
5.4 KiB
C
#include "../../uwsgi.h"
|
|
|
|
#ifdef UWSGI_ROUTING
|
|
|
|
extern struct uwsgi_server uwsgi;
|
|
|
|
/*
|
|
|
|
by Unbit
|
|
|
|
syntax:
|
|
|
|
route = /^foobar1(.*)/ cache:key=foo$1poo,content_type=text/html,name=foobar
|
|
|
|
*/
|
|
|
|
struct uwsgi_router_cache_conf {
|
|
|
|
// the name of the cache
|
|
char *name;
|
|
size_t name_len;
|
|
|
|
char *key;
|
|
size_t key_len;
|
|
|
|
char *content_type;
|
|
size_t content_type_len;
|
|
|
|
struct uwsgi_cache *cache;
|
|
|
|
char *expires_str;
|
|
uint64_t expires;
|
|
|
|
};
|
|
|
|
// be tolerant on errors
|
|
static int uwsgi_routing_func_cache_store(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
|
struct uwsgi_router_cache_conf *urcc = (struct uwsgi_router_cache_conf *) ur->data2;
|
|
|
|
// overwrite previous run
|
|
if (wsgi_req->cache_it) {
|
|
uwsgi_buffer_destroy(wsgi_req->cache_it);
|
|
wsgi_req->cache_it = NULL;
|
|
}
|
|
|
|
if (wsgi_req->cache_it_to) {
|
|
uwsgi_buffer_destroy(wsgi_req->cache_it_to);
|
|
wsgi_req->cache_it_to = NULL;
|
|
}
|
|
|
|
// build key and name
|
|
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
|
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
|
|
|
wsgi_req->cache_it = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->key, urcc->key_len);
|
|
if (!wsgi_req->cache_it) return UWSGI_ROUTE_NEXT;
|
|
|
|
if (urcc->name) {
|
|
wsgi_req->cache_it_to = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->name, urcc->name_len);
|
|
if (!wsgi_req->cache_it_to) {
|
|
uwsgi_buffer_destroy(wsgi_req->cache_it);
|
|
wsgi_req->cache_it = NULL;
|
|
}
|
|
}
|
|
|
|
wsgi_req->cache_it_expires = urcc->expires;
|
|
|
|
return UWSGI_ROUTE_NEXT;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
|
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
|
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->key, urcc->key_len);
|
|
if (!ub) return UWSGI_ROUTE_BREAK;
|
|
|
|
uint64_t valsize = 0;
|
|
char *value = uwsgi_cache_magic_get(ub->buf, ub->pos, &valsize, urcc->name);
|
|
uwsgi_buffer_destroy(ub);
|
|
if (value) {
|
|
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
|
|
if (uwsgi_response_add_content_type(wsgi_req, urcc->content_type, urcc->content_type_len)) goto error;
|
|
if (uwsgi_response_add_content_length(wsgi_req, valsize)) goto error;
|
|
uwsgi_response_write_body_do(wsgi_req, value, valsize);
|
|
free(value);
|
|
if (ur->custom)
|
|
return UWSGI_ROUTE_NEXT;
|
|
return UWSGI_ROUTE_BREAK;
|
|
}
|
|
|
|
return UWSGI_ROUTE_NEXT;
|
|
error:
|
|
free(value);
|
|
return UWSGI_ROUTE_BREAK;
|
|
}
|
|
|
|
static int uwsgi_router_cache_store(struct uwsgi_route *ur, char *args) {
|
|
ur->func = uwsgi_routing_func_cache_store;
|
|
ur->data = args;
|
|
ur->data_len = strlen(args);
|
|
struct uwsgi_router_cache_conf *urcc = uwsgi_calloc(sizeof(struct uwsgi_router_cache_conf));
|
|
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
|
|
"key", &urcc->key,
|
|
"name", &urcc->name,
|
|
"expires", &urcc->expires_str, NULL)) {
|
|
uwsgi_log("invalid cachestore route syntax: %s\n", args);
|
|
goto error;
|
|
}
|
|
|
|
if (urcc->key) {
|
|
urcc->key_len = strlen(urcc->key);
|
|
}
|
|
|
|
if (urcc->name) {
|
|
urcc->name_len = strlen(urcc->name);
|
|
}
|
|
|
|
if (!urcc->key) {
|
|
uwsgi_log("invalid cachestore route syntax: you need to specify a cache key\n");
|
|
goto error;
|
|
}
|
|
|
|
if (urcc->expires_str) {
|
|
urcc->expires = strtoul(urcc->expires_str, NULL, 10);
|
|
}
|
|
|
|
ur->data2 = urcc;
|
|
return 0;
|
|
error:
|
|
if (urcc->key) free(urcc->key);
|
|
if (urcc->name) free(urcc->name);
|
|
if (urcc->expires_str) free(urcc->expires_str);
|
|
free(urcc);
|
|
return -1;
|
|
}
|
|
|
|
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);
|
|
struct uwsgi_router_cache_conf *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,
|
|
"name", &urcc->name,
|
|
NULL)) {
|
|
uwsgi_log("invalid route syntax: %s\n", args);
|
|
exit(1);
|
|
}
|
|
|
|
if (urcc->key) {
|
|
urcc->key_len = strlen(urcc->key);
|
|
}
|
|
|
|
if (!urcc->key) {
|
|
uwsgi_log("invalid route syntax: you need to specify a cache key\n");
|
|
exit(1);
|
|
}
|
|
|
|
if (!urcc->content_type) urcc->content_type = "text/html";
|
|
|
|
urcc->content_type_len = strlen(urcc->content_type);
|
|
|
|
ur->data2 = urcc;
|
|
return 0;
|
|
}
|
|
|
|
static int uwsgi_router_cache_continue(struct uwsgi_route *ur, char *args) {
|
|
uwsgi_router_cache(ur, args);
|
|
ur->custom = 1;
|
|
return 0;
|
|
}
|
|
|
|
static void router_cache_register() {
|
|
uwsgi_register_router("cache", uwsgi_router_cache);
|
|
uwsgi_register_router("cache-continue", uwsgi_router_cache_continue);
|
|
uwsgi_register_router("cachestore", uwsgi_router_cache_store);
|
|
uwsgi_register_router("cache-store", uwsgi_router_cache_store);
|
|
}
|
|
|
|
struct uwsgi_plugin router_cache_plugin = {
|
|
.name = "router_cache",
|
|
.on_load = router_cache_register,
|
|
};
|
|
|
|
#else
|
|
struct uwsgi_plugin router_cache_plugin = {
|
|
.name = "router_cache",
|
|
};
|
|
#endif
|