Sun, 07 Dec 2025 17:06:21 +0100
add rewrite directive
--- a/src/server/daemon/config.c Sun Dec 07 16:31:21 2025 +0100 +++ b/src/server/daemon/config.c Sun Dec 07 17:06:21 2025 +0100 @@ -1218,7 +1218,7 @@ } ACLList* acl_config_convert(ServerConfiguration *cfg, ACLConfig *acl) { - CxAllocator *a = cfg->a; + const CxAllocator *a = cfg->a; WSAcl *acllist = cxMalloc(cfg->a, sizeof(WSAcl)); acllist->acl.check = (acl_check_f)wsacl_check;
--- a/src/server/daemon/config.h Sun Dec 07 16:31:21 2025 +0100 +++ b/src/server/daemon/config.h Sun Dec 07 17:06:21 2025 +0100 @@ -71,7 +71,7 @@ struct ServerConfiguration { pool_handle_t *pool; - CxAllocator *a; + const CxAllocator *a; CxList *destr; // list of ScfgDestr
--- a/src/server/daemon/keyfile_auth.c Sun Dec 07 16:31:21 2025 +0100 +++ b/src/server/daemon/keyfile_auth.c Sun Dec 07 17:06:21 2025 +0100 @@ -38,7 +38,7 @@ #include "keyfile_auth.h" -Keyfile* keyfile_new(CxAllocator *a) { +Keyfile* keyfile_new(const CxAllocator *a) { Keyfile *keyfile = cxCalloc(a, 1, sizeof(Keyfile)); if(!keyfile) { return NULL;
--- a/src/server/daemon/keyfile_auth.h Sun Dec 07 16:31:21 2025 +0100 +++ b/src/server/daemon/keyfile_auth.h Sun Dec 07 17:06:21 2025 +0100 @@ -61,7 +61,7 @@ size_t hashlen; }; -Keyfile* keyfile_new(CxAllocator *a); +Keyfile* keyfile_new(const CxAllocator *a); int keyfile_add_user( Keyfile *keyfile,
--- a/src/server/daemon/location.c Sun Dec 07 16:31:21 2025 +0100 +++ b/src/server/daemon/location.c Sun Dec 07 17:06:21 2025 +0100 @@ -29,8 +29,10 @@ #include "location.h" #include "config.h" #include "request.h" +#include "rewrite.h" #include "../util/util.h" #include "../util/pblock.h" +#include "../util/pool.h" #include "vserver.h" #include <cx/linked_list.h> #include <cx/array_list.h> @@ -84,6 +86,36 @@ return 1; } location_list_add(location, sub_location); + } else if(!cx_strcasecmp(name, "Rewrite")) { + cxmutstr regex = (cxmutstr){NULL, 0}; + cxmutstr url = (cxmutstr){NULL, 0}; + if(argc == 1) { + // no custom rewrite regex + url = dir->args->value; + } else if(argc == 2) { + // regex, url + regex = dir->args->value; + url = dir->args->next->value; + } else { + log_ereport(LOG_FAILURE, "rewrite [regex] <url>: illegal argc %d", argc); + return 1; + } + + RewriteRule *rule = rewrite_rule_create(cfg, regex, url); + if(!rule) { + return 1; + } + + if(!location->rewrite) { + location->rewrite = cxLinkedListCreate(a, NULL, CX_STORE_POINTERS); + if(!location->rewrite) { + return 1; + } + } + + if(cxListAdd(location->rewrite, rule)) { + return 1; + } } return 0; @@ -197,7 +229,7 @@ return 0; } -WSLocationConfig* location_match_and_get_config(pool_handle_t *pool, cxstring uri, WSLocation *loc) { +WSLocationConfig* location_match_and_get_config(pool_handle_t *pool, Request *rq, cxstring uri, WSLocation *loc) { WSLocationConfig *config = pool_malloc(pool, sizeof(WSLocationConfig)); if(!config) { return NULL; @@ -208,8 +240,22 @@ config->match[i].rm_eo = -1; } + const CxAllocator *a = pool_allocator(pool); + while(loc) { if(location_match(loc, uri, config->match)) { + // apply rewrite rules + CxIterator iter = cxListIterator(loc->rewrite); + cx_foreach(RewriteRule *, rule, iter) { + char *new_url = NULL; + if(!rewrite_url(rule, config->match, WS_LOCATION_NMATCH, a, uri.ptr, &new_url)) { + pblock_removekey(pb_key_uri, rq->reqpb); + if(pblock_kvinsert(pb_key_uri, new_url, strlen(new_url), rq->reqpb) == NULL) { + return NULL; + } + } + } + if(location_apply_config(config, loc)) { return NULL; } @@ -225,5 +271,5 @@ NSAPIRequest *req = (NSAPIRequest*)rq; WSLocation *loc = req->vs->locations_begin; char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); - return location_match_and_get_config(sn->pool, cx_str(uri), loc); + return location_match_and_get_config(sn->pool, rq, cx_str(uri), loc); }
--- a/src/server/daemon/location.h Sun Dec 07 16:31:21 2025 +0100 +++ b/src/server/daemon/location.h Sun Dec 07 17:06:21 2025 +0100 @@ -138,6 +138,12 @@ WSLocationConfig config; /* + * list of rewrite rules + */ + CxList *rewrite; + + + /* * extended settings * key: directive name * value: char* @@ -154,7 +160,7 @@ int location_apply_config(WSLocationConfig *target, WSLocation *loc); int location_match(WSLocation *loc, cxstring uri, regmatch_t *match); -WSLocationConfig* location_match_and_get_config(pool_handle_t *pool, cxstring uri, WSLocation *loc); +WSLocationConfig* location_match_and_get_config(pool_handle_t *pool, Request *rq, cxstring uri, WSLocation *loc); WSLocationConfig* cfg_location_match(Session *sn, Request *rq); #ifdef __cplusplus
--- a/src/server/daemon/rewrite.c Sun Dec 07 16:31:21 2025 +0100 +++ b/src/server/daemon/rewrite.c Sun Dec 07 17:06:21 2025 +0100 @@ -27,9 +27,12 @@ */ #include "rewrite.h" +#include "config.h" -RewriteRule* rewrite_rule_create(const CxAllocator *a, cxmutstr regex, cxmutstr url) { +RewriteRule* rewrite_rule_create(ServerConfiguration *cfg, cxmutstr regex, cxmutstr url) { + const CxAllocator *a = cfg->a; + regex_t reg; if(regex.ptr) { if(regcomp(®, regex.ptr, REG_EXTENDED)) {
--- a/src/server/daemon/rewrite.h Sun Dec 07 16:31:21 2025 +0100 +++ b/src/server/daemon/rewrite.h Sun Dec 07 17:06:21 2025 +0100 @@ -59,7 +59,7 @@ StringTemplate *url; } RewriteRule; -RewriteRule* rewrite_rule_create(const CxAllocator *a, cxmutstr regex, cxmutstr url); +RewriteRule* rewrite_rule_create(ServerConfiguration *cfg, cxmutstr regex, cxmutstr url); int rewrite_url( RewriteRule *rule,
--- a/src/server/safs/nametrans.c Sun Dec 07 16:31:21 2025 +0100 +++ b/src/server/safs/nametrans.c Sun Dec 07 17:06:21 2025 +0100 @@ -288,7 +288,7 @@ return REQ_ABORTED; } req->location = config; - + if(config->vfs.ptr) { VFS *vfs = vfs_create(sn, rq, config->vfs.ptr, pb, NULL); if(!vfs) {
--- a/src/server/test/rewrite.c Sun Dec 07 16:31:21 2025 +0100 +++ b/src/server/test/rewrite.c Sun Dec 07 17:06:21 2025 +0100 @@ -29,15 +29,21 @@ #include "rewrite.h" #include "../daemon/rewrite.h" +#include "../daemon/config.h" #include <cx/mempool.h> +#include <cx/linked_list.h> #include <string.h> CX_TEST(test_rewrite_rule_create) { CxMempool *mp = cxMempoolCreate(100, CX_MEMPOOL_TYPE_ADVANCED); const CxAllocator *a = mp->allocator; + ServerConfiguration cfg = { NULL }; + cfg.a = a; + cfg.destr = cxLinkedListCreate(a, NULL, sizeof(ScfgDestr)); + CX_TEST_DO { - RewriteRule *rule = rewrite_rule_create(a, cx_mutstr(NULL), cx_mutstr("/rewrite")); + RewriteRule *rule = rewrite_rule_create(&cfg, cx_mutstr(NULL), cx_mutstr("/rewrite")); CX_TEST_ASSERT(rule != NULL); CX_TEST_ASSERT(!rule->has_regex); CX_TEST_ASSERT(rule->url != NULL); @@ -45,12 +51,13 @@ cxmutstr newuri = string_template_build_string(rule->url, a, NULL, NULL); CX_TEST_ASSERT(!cx_strcmp(newuri, "/rewrite")); - RewriteRule *rule2 = rewrite_rule_create(a, cx_mutstr("/path/(.*)/files/"), cx_mutstr("/rewrite/$1/")); + RewriteRule *rule2 = rewrite_rule_create(&cfg, cx_mutstr("/path/(.*)/files/"), cx_mutstr("/rewrite/$1/")); CX_TEST_ASSERT(rule2 != NULL); CX_TEST_ASSERT(rule2->has_regex); CX_TEST_ASSERT(rule2->url != NULL); } + server_config_destroy(&cfg); cxMempoolFree(mp); } @@ -58,6 +65,10 @@ CxMempool *mp = cxMempoolCreate(100, CX_MEMPOOL_TYPE_ADVANCED); const CxAllocator *a = mp->allocator; + ServerConfiguration cfg = { NULL }; + cfg.a = a; + cfg.destr = cxLinkedListCreate(a, NULL, sizeof(ScfgDestr)); + RewriteRule rule; memset(&rule, 0, sizeof(RewriteRule)); rule.url = string_template_compile(a, cx_str("/static/")); @@ -71,5 +82,6 @@ CX_TEST_ASSERT(!strcmp(new_url, "/static/")); } + server_config_destroy(&cfg); cxMempoolFree(mp); }