mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-05-14 02:33:51 +00:00
633 lines
20 KiB
C
633 lines
20 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 *var;
|
|
size_t var_len;
|
|
|
|
char *value;
|
|
size_t value_len;
|
|
|
|
// use mime types ?
|
|
char *mime;
|
|
|
|
char *as_num;
|
|
|
|
#ifdef UWSGI_ZLIB
|
|
char *gzip;
|
|
size_t gzip_len;
|
|
#endif
|
|
|
|
char *content_type;
|
|
size_t content_type_len;
|
|
|
|
char *content_encoding;
|
|
size_t content_encoding_len;
|
|
|
|
struct uwsgi_cache *cache;
|
|
|
|
char *expires_str;
|
|
uint64_t expires;
|
|
|
|
int64_t default_num;
|
|
|
|
uint64_t flags;
|
|
|
|
char *status_str;
|
|
int status;
|
|
char *no_offload;
|
|
|
|
char *no_cl;
|
|
};
|
|
|
|
// this is allocated for each transformation
|
|
struct uwsgi_transformation_cache_conf {
|
|
struct uwsgi_buffer *cache_it;
|
|
#ifdef UWSGI_ZLIB
|
|
struct uwsgi_buffer *cache_it_gzip;
|
|
#endif
|
|
|
|
int status;
|
|
struct uwsgi_buffer *value;
|
|
|
|
struct uwsgi_buffer *cache_it_to;
|
|
uint64_t cache_it_expires;
|
|
};
|
|
|
|
static int transform_cache(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
|
|
struct uwsgi_transformation_cache_conf *utcc = (struct uwsgi_transformation_cache_conf *) ut->data;
|
|
struct uwsgi_buffer *ub = ut->chunk;
|
|
// force value
|
|
if (utcc->value) {
|
|
ub = utcc->value;
|
|
}
|
|
// store only successfull response
|
|
if (wsgi_req->write_errors == 0 && (wsgi_req->status == 200 || (utcc->status && wsgi_req->status == utcc->status)) && ub->pos > 0) {
|
|
if (utcc->cache_it) {
|
|
uwsgi_cache_magic_set(utcc->cache_it->buf, utcc->cache_it->pos, ub->buf, ub->pos, utcc->cache_it_expires,
|
|
UWSGI_CACHE_FLAG_UPDATE, utcc->cache_it_to ? utcc->cache_it_to->buf : NULL);
|
|
#ifdef UWSGI_ZLIB
|
|
if (utcc->cache_it_gzip) {
|
|
struct uwsgi_buffer *gzipped = uwsgi_gzip(ub->buf, ub->pos);
|
|
if (gzipped) {
|
|
uwsgi_cache_magic_set(utcc->cache_it_gzip->buf, utcc->cache_it_gzip->pos, gzipped->buf, gzipped->pos, utcc->cache_it_expires,
|
|
UWSGI_CACHE_FLAG_UPDATE, utcc->cache_it_to ? utcc->cache_it_to->buf : NULL);
|
|
uwsgi_buffer_destroy(gzipped);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// free resources
|
|
if (utcc->cache_it) uwsgi_buffer_destroy(utcc->cache_it);
|
|
#ifdef UWSGI_ZLIB
|
|
if (utcc->cache_it_gzip) uwsgi_buffer_destroy(utcc->cache_it_gzip);
|
|
#endif
|
|
if (utcc->cache_it_to) uwsgi_buffer_destroy(utcc->cache_it_to);
|
|
if (utcc->value) uwsgi_buffer_destroy(utcc->value);
|
|
free(utcc);
|
|
return 0;
|
|
}
|
|
|
|
|
|
// 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;
|
|
|
|
struct uwsgi_transformation_cache_conf *utcc = uwsgi_calloc(sizeof(struct uwsgi_transformation_cache_conf));
|
|
|
|
// build key and name
|
|
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
|
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
|
|
|
utcc->cache_it = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->key, urcc->key_len);
|
|
if (!utcc->cache_it) goto error;
|
|
|
|
if (urcc->name) {
|
|
utcc->cache_it_to = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->name, urcc->name_len);
|
|
if (!utcc->cache_it_to) goto error;
|
|
}
|
|
|
|
if (urcc->value) {
|
|
utcc->value = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->value, urcc->value_len);
|
|
if (!utcc->value) goto error;
|
|
}
|
|
|
|
utcc->status = urcc->status;
|
|
|
|
#ifdef UWSGI_ZLIB
|
|
if (urcc->gzip) {
|
|
utcc->cache_it_gzip = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->gzip, urcc->gzip_len);
|
|
if (!utcc->cache_it_gzip) goto error;
|
|
}
|
|
#endif
|
|
utcc->cache_it_expires = urcc->expires;
|
|
|
|
uwsgi_add_transformation(wsgi_req, transform_cache, utcc);
|
|
|
|
return UWSGI_ROUTE_NEXT;
|
|
|
|
error:
|
|
if (utcc->cache_it) uwsgi_buffer_destroy(utcc->cache_it);
|
|
#ifdef UWSGI_ZLIB
|
|
if (utcc->cache_it_gzip) uwsgi_buffer_destroy(utcc->cache_it_gzip);
|
|
#endif
|
|
if (utcc->cache_it_to) uwsgi_buffer_destroy(utcc->cache_it_to);
|
|
free(utcc);
|
|
return UWSGI_ROUTE_NEXT;
|
|
}
|
|
|
|
static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
|
|
|
char *mime_type = NULL;
|
|
size_t mime_type_len = 0;
|
|
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;
|
|
uint64_t expires = 0;
|
|
char *value = uwsgi_cache_magic_get(ub->buf, ub->pos, &valsize, &expires, urcc->name);
|
|
if (urcc->mime && value) {
|
|
mime_type = uwsgi_get_mime_type(ub->buf, ub->pos, &mime_type_len);
|
|
}
|
|
uwsgi_buffer_destroy(ub);
|
|
if (value) {
|
|
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
|
|
if (mime_type) {
|
|
uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len);
|
|
}
|
|
else {
|
|
if (uwsgi_response_add_content_type(wsgi_req, urcc->content_type, urcc->content_type_len)) goto error;
|
|
}
|
|
if (urcc->content_encoding_len) {
|
|
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, urcc->content_encoding, urcc->content_encoding_len)) goto error;
|
|
}
|
|
if (expires) {
|
|
if (uwsgi_response_add_expires(wsgi_req, expires)) goto error;
|
|
}
|
|
if (!urcc->no_cl) {
|
|
if (uwsgi_response_add_content_length(wsgi_req, valsize)) goto error;
|
|
}
|
|
if (wsgi_req->socket->can_offload && !ur->custom && !urcc->no_offload) {
|
|
if (!uwsgi_offload_request_memory_do(wsgi_req, value, valsize)) {
|
|
wsgi_req->via = UWSGI_VIA_OFFLOAD;
|
|
return UWSGI_ROUTE_BREAK;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// place a cache value in a request var
|
|
static int uwsgi_routing_func_cachevar(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, NULL, urcc->name);
|
|
uwsgi_buffer_destroy(ub);
|
|
if (value) {
|
|
if (urcc->as_num) {
|
|
char *tmp = value;
|
|
if (valsize == 8) {
|
|
int64_t *num = (int64_t *) value;
|
|
value = uwsgi_64bit2str(*num);
|
|
}
|
|
else {
|
|
value = uwsgi_64bit2str(0);
|
|
}
|
|
free(tmp);
|
|
}
|
|
if (!uwsgi_req_append(wsgi_req, urcc->var, urcc->var_len, value, valsize)) {
|
|
free(value);
|
|
return UWSGI_ROUTE_BREAK;
|
|
}
|
|
free(value);
|
|
}
|
|
|
|
return UWSGI_ROUTE_NEXT;
|
|
}
|
|
|
|
// set a cache item
|
|
static int uwsgi_routing_func_cacheset(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;
|
|
|
|
struct uwsgi_buffer *ub_val = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->value, urcc->value_len);
|
|
if (!ub_val) {
|
|
uwsgi_buffer_destroy(ub);
|
|
return UWSGI_ROUTE_BREAK;
|
|
}
|
|
|
|
if (uwsgi_cache_magic_set(ub->buf, ub->pos, ub_val->buf, ub_val->pos, urcc->expires, 0, urcc->name)) {
|
|
uwsgi_buffer_destroy(ub);
|
|
uwsgi_buffer_destroy(ub_val);
|
|
return UWSGI_ROUTE_BREAK;
|
|
}
|
|
uwsgi_buffer_destroy(ub);
|
|
uwsgi_buffer_destroy(ub_val);
|
|
return UWSGI_ROUTE_NEXT;
|
|
}
|
|
|
|
// cacheinc/cachedec/cachemul/cachediv
|
|
static int uwsgi_routing_func_cachemath(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;
|
|
|
|
int64_t num = urcc->default_num;
|
|
|
|
if (urcc->value) {
|
|
struct uwsgi_buffer *ub_val = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->value, urcc->value_len);
|
|
if (!ub_val) {
|
|
uwsgi_buffer_destroy(ub);
|
|
return UWSGI_ROUTE_BREAK;
|
|
}
|
|
num = strtol(ub_val->buf, NULL, 10);
|
|
uwsgi_buffer_destroy(ub_val);
|
|
}
|
|
|
|
if (uwsgi_cache_magic_set(ub->buf, ub->pos, (char *) &num, 8, urcc->expires, urcc->flags, urcc->name)) {
|
|
uwsgi_buffer_destroy(ub);
|
|
return UWSGI_ROUTE_BREAK;
|
|
}
|
|
uwsgi_buffer_destroy(ub);
|
|
return UWSGI_ROUTE_NEXT;
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
#ifdef UWSGI_ZLIB
|
|
"gzip", &urcc->gzip,
|
|
#endif
|
|
"name", &urcc->name,
|
|
"value", &urcc->value,
|
|
"status", &urcc->status_str,
|
|
"code", &urcc->status_str,
|
|
"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);
|
|
}
|
|
|
|
#ifdef UWSGI_ZLIB
|
|
if (urcc->gzip) {
|
|
urcc->gzip_len = strlen(urcc->gzip);
|
|
}
|
|
#endif
|
|
|
|
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);
|
|
}
|
|
|
|
if (urcc->value) {
|
|
urcc->value_len = strlen(urcc->value);
|
|
}
|
|
|
|
if (urcc->status_str) {
|
|
urcc->status = atoi(urcc->status_str);
|
|
}
|
|
|
|
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,
|
|
"content_encoding", &urcc->content_encoding,
|
|
"mime", &urcc->mime,
|
|
"name", &urcc->name,
|
|
"no_offload", &urcc->no_offload,
|
|
"no_content_length", &urcc->no_cl,
|
|
"no_cl", &urcc->no_cl,
|
|
"nocl", &urcc->no_cl,
|
|
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);
|
|
|
|
if (urcc->content_encoding) {
|
|
urcc->content_encoding_len = strlen(urcc->content_encoding);
|
|
}
|
|
|
|
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 struct uwsgi_router_cache_conf *uwsgi_router_cachemath(struct uwsgi_route *ur, char *args) {
|
|
ur->func = uwsgi_routing_func_cachemath;
|
|
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,
|
|
"value", &urcc->value,
|
|
"name", &urcc->name,
|
|
"expires", &urcc->expires_str, NULL)) {
|
|
uwsgi_log("invalid cachemath route syntax: %s\n", args);
|
|
goto error;
|
|
}
|
|
|
|
if (urcc->key) {
|
|
urcc->key_len = strlen(urcc->key);
|
|
}
|
|
|
|
if (urcc->value) {
|
|
urcc->value_len = strlen(urcc->value);
|
|
}
|
|
|
|
if (urcc->name) {
|
|
urcc->name_len = strlen(urcc->name);
|
|
}
|
|
|
|
if (!urcc->key) {
|
|
uwsgi_log("invalid cachemath route syntax: you need to specify a cache key\n");
|
|
goto error;
|
|
}
|
|
|
|
if (urcc->expires_str) {
|
|
urcc->expires = strtoul(urcc->expires_str, NULL, 10);
|
|
}
|
|
|
|
urcc->flags = UWSGI_CACHE_FLAG_UPDATE|UWSGI_CACHE_FLAG_MATH|UWSGI_CACHE_FLAG_FIXEXPIRE;
|
|
ur->data2 = urcc;
|
|
return urcc;
|
|
error:
|
|
if (urcc->key) free(urcc->key);
|
|
if (urcc->name) free(urcc->name);
|
|
if (urcc->value) free(urcc->value);
|
|
if (urcc->expires_str) free(urcc->expires_str);
|
|
free(urcc);
|
|
return NULL;
|
|
}
|
|
|
|
static int uwsgi_router_cacheinc(struct uwsgi_route *ur, char *args) {
|
|
struct uwsgi_router_cache_conf *urcc = uwsgi_router_cachemath(ur, args);
|
|
if (!urcc) return -1;
|
|
urcc->default_num = 1;
|
|
urcc->flags |= UWSGI_CACHE_FLAG_INC;
|
|
return 0;
|
|
}
|
|
|
|
static int uwsgi_router_cachedec(struct uwsgi_route *ur, char *args) {
|
|
struct uwsgi_router_cache_conf *urcc = uwsgi_router_cachemath(ur, args);
|
|
if (!urcc) return -1;
|
|
urcc->default_num = 1;
|
|
urcc->flags |= UWSGI_CACHE_FLAG_DEC;
|
|
return 0;
|
|
}
|
|
|
|
static int uwsgi_router_cachemul(struct uwsgi_route *ur, char *args) {
|
|
struct uwsgi_router_cache_conf *urcc = uwsgi_router_cachemath(ur, args);
|
|
if (!urcc) return -1;
|
|
urcc->default_num = 2;
|
|
urcc->flags |= UWSGI_CACHE_FLAG_MUL;
|
|
return 0;
|
|
}
|
|
|
|
static int uwsgi_router_cachediv(struct uwsgi_route *ur, char *args) {
|
|
struct uwsgi_router_cache_conf *urcc = uwsgi_router_cachemath(ur, args);
|
|
if (!urcc) return -1;
|
|
urcc->default_num = 2;
|
|
urcc->flags |= UWSGI_CACHE_FLAG_DIV;
|
|
return 0;
|
|
}
|
|
|
|
static int uwsgi_router_cacheset(struct uwsgi_route *ur, char *args) {
|
|
ur->func = uwsgi_routing_func_cacheset;
|
|
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,
|
|
"value", &urcc->value,
|
|
"name", &urcc->name,
|
|
"expires", &urcc->expires_str, NULL)) {
|
|
uwsgi_log("invalid cacheset route syntax: %s\n", args);
|
|
goto error;
|
|
}
|
|
|
|
if (urcc->key) {
|
|
urcc->key_len = strlen(urcc->key);
|
|
}
|
|
|
|
if (urcc->value) {
|
|
urcc->value_len = strlen(urcc->value);
|
|
}
|
|
|
|
if (urcc->name) {
|
|
urcc->name_len = strlen(urcc->name);
|
|
}
|
|
|
|
if (!urcc->key || !urcc->value) {
|
|
uwsgi_log("invalid cacheset route syntax: you need to specify a cache key and a value\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->value) free(urcc->value);
|
|
if (urcc->expires_str) free(urcc->expires_str);
|
|
free(urcc);
|
|
return -1;
|
|
}
|
|
|
|
|
|
static int uwsgi_router_cachevar(struct uwsgi_route *ur, char *args) {
|
|
ur->func = uwsgi_routing_func_cachevar;
|
|
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,
|
|
"var", &urcc->var,
|
|
"name", &urcc->name,
|
|
"num", &urcc->as_num,
|
|
"as_num", &urcc->as_num,
|
|
NULL)) {
|
|
uwsgi_log("invalid route syntax: %s\n", args);
|
|
exit(1);
|
|
}
|
|
|
|
if (urcc->key) {
|
|
urcc->key_len = strlen(urcc->key);
|
|
}
|
|
|
|
if (urcc->var) {
|
|
urcc->var_len = strlen(urcc->var);
|
|
}
|
|
|
|
if (!urcc->key || !urcc->var) {
|
|
uwsgi_log("invalid route syntax: you need to specify a cache key and a request var\n");
|
|
exit(1);
|
|
}
|
|
|
|
ur->data2 = urcc;
|
|
return 0;
|
|
}
|
|
|
|
static int uwsgi_route_condition_incache(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
|
int ret = 0;
|
|
char *key = NULL;
|
|
size_t key_len = 0;
|
|
char *name = NULL;
|
|
|
|
if (uwsgi_kvlist_parse(ur->subject_str, ur->subject_str_len, ',', '=',
|
|
"key", &key,
|
|
"name", &name,
|
|
NULL)) {
|
|
return 0;
|
|
}
|
|
|
|
if (!key) goto end;
|
|
|
|
key_len = strlen(key);
|
|
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, key, key_len);
|
|
if (!ub) goto end;
|
|
|
|
ret = uwsgi_cache_magic_exists(ub->buf, ub->pos, name);
|
|
uwsgi_buffer_destroy(ub);
|
|
|
|
end:
|
|
if (key) free(key);
|
|
if (name) free(name);
|
|
return ret;
|
|
}
|
|
|
|
static void router_cache_register() {
|
|
uwsgi_register_router("cache", uwsgi_router_cache);
|
|
uwsgi_register_router("cache-continue", uwsgi_router_cache_continue);
|
|
uwsgi_register_router("cachevar", uwsgi_router_cachevar);
|
|
uwsgi_register_router("cacheset", uwsgi_router_cacheset);
|
|
uwsgi_register_router("cachestore", uwsgi_router_cache_store);
|
|
uwsgi_register_router("cache-store", uwsgi_router_cache_store);
|
|
uwsgi_register_route_condition("incache", uwsgi_route_condition_incache);
|
|
|
|
uwsgi_register_router("cacheinc", uwsgi_router_cacheinc);
|
|
uwsgi_register_router("cachedec", uwsgi_router_cachedec);
|
|
uwsgi_register_router("cachemul", uwsgi_router_cachemul);
|
|
uwsgi_register_router("cachediv", uwsgi_router_cachediv);
|
|
}
|
|
|
|
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
|