add rewrite directive

Sun, 07 Dec 2025 17:06:21 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 07 Dec 2025 17:06:21 +0100
changeset 651
ed74879c7041
parent 650
3e4f9cdd70b8
child 652
dd90c858eb74

add rewrite directive

src/server/daemon/config.c file | annotate | diff | comparison | revisions
src/server/daemon/config.h file | annotate | diff | comparison | revisions
src/server/daemon/keyfile_auth.c file | annotate | diff | comparison | revisions
src/server/daemon/keyfile_auth.h file | annotate | diff | comparison | revisions
src/server/daemon/location.c file | annotate | diff | comparison | revisions
src/server/daemon/location.h file | annotate | diff | comparison | revisions
src/server/daemon/rewrite.c file | annotate | diff | comparison | revisions
src/server/daemon/rewrite.h file | annotate | diff | comparison | revisions
src/server/safs/nametrans.c file | annotate | diff | comparison | revisions
src/server/test/rewrite.c file | annotate | diff | comparison | revisions
--- 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(&reg, 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);
 }

mercurial