patplex: Add reparse action.
authorFredrik Tolf <fredrik@dolda2000.com>
Sat, 17 Jul 2021 23:31:38 +0000 (01:31 +0200)
committerFredrik Tolf <fredrik@dolda2000.com>
Sat, 17 Jul 2021 23:31:38 +0000 (01:31 +0200)
doc/patplex.doc
src/patplex.c

index 5a60e96..a9ebe69 100644 (file)
@@ -102,14 +102,22 @@ rules are recognized:
        -10* (see below).
 
 In addition to the rules, a *match* stanza must contain exactly one
-follow-up line specifying the action to take if it matches. Currently,
-only the *handler* action is recognized:
+follow-up line specifying the action to take if it matches. The
+following actions are supported:
 
 *handler* 'HANDLER'::
 
        'HANDLER' must be a named handler as declared by a *child* or
        *fchild* stanza, to which the request is passed.
 
+*reparse*::
+
+       Apply any side-effects as required by the match stanza (such
+       as rest-string or header modifications), and then retry the
+       matching of the request. During the rematching, the stanza
+       containing the *reparse* action will be disabled. Multiple
+       *reparse* stanzas may be used recursively.
+
 Additionally, a *match* stanza may contain any of the following,
 optional lines:
 
index f76cc72..e893bc0 100644 (file)
@@ -46,6 +46,9 @@
 #define PATFL_MSS 1
 #define PATFL_UNQ 2
 
+#define HND_CHILD 1
+#define HND_REPARSE 2
+
 struct config {
     struct child *children;
     struct pattern *patterns;
@@ -69,7 +72,7 @@ struct pattern {
     char *childnm;
     struct rule **rules;
     char *restpat;
-    int prio;
+    int handler, prio, disable;
 };
 
 static struct config *gconfig, *lconfig;
@@ -254,6 +257,9 @@ static struct pattern *parsepattern(struct cfstate *s)
            if(pat->childnm != NULL)
                free(pat->childnm);
            pat->childnm = sstrdup(s->argv[1]);
+           pat->handler = HND_CHILD;
+       } else if(!strcmp(s->argv[0], "reparse")) {
+           pat->handler = HND_REPARSE;
        } else if(!strcmp(s->argv[0], "restpat")) {
            if(s->argc < 2) {
                flog(LOG_WARNING, "%s:%i: missing pattern for `restpat' directive", s->file, s->lno);
@@ -287,7 +293,7 @@ static struct pattern *parsepattern(struct cfstate *s)
        freepattern(pat);
        return(NULL);
     }
-    if(pat->childnm == NULL) {
+    if(pat->handler == 0) {
        flog(LOG_WARNING, "%s:%i: missing handler in match declaration", s->file, sl);
        freepattern(pat);
        return(NULL);
@@ -427,7 +433,7 @@ static struct match *findmatch(struct config *cf, struct hthead *req, struct mat
     
     mstr = NULL;
     for(pat = cf->patterns; pat != NULL; pat = pat->next) {
-       if(match && (pat->prio <= match->pat->prio))
+       if(pat->disable || (match && (pat->prio <= match->pat->prio)))
            continue;
        rmo = -1;
        for(i = 0; (rule = pat->rules[i]) != NULL; i++) {
@@ -522,21 +528,30 @@ static void serve(struct hthead *req, int fd)
        simpleerror(fd, 404, "Not Found", "The requested resource could not be found on this server.");
        return;
     }
-    ch = NULL;
-    if(ch == NULL)
-       ch = getchild(lconfig, match->pat->childnm);
-    if((ch == NULL) && (gconfig != NULL))
-       ch = getchild(gconfig, match->pat->childnm);
-    if(ch == NULL) {
-       flog(LOG_ERR, "child %s requested, but was not declared", match->pat->childnm);
-       simpleerror(fd, 500, "Configuration Error", "The server is erroneously configured. Handler %s was requested, but not declared.", match->pat->childnm);
-       freematch(match);
-       return;
-    }
-    
     execmatch(req, match);
-    if(childhandle(ch, req, fd, NULL, NULL))
-       childerror(req, fd);
+    switch(match->pat->handler) {
+    case HND_CHILD:
+       ch = NULL;
+       if(ch == NULL)
+           ch = getchild(lconfig, match->pat->childnm);
+       if((ch == NULL) && (gconfig != NULL))
+           ch = getchild(gconfig, match->pat->childnm);
+       if(ch == NULL) {
+           flog(LOG_ERR, "child %s requested, but was not declared", match->pat->childnm);
+           simpleerror(fd, 500, "Configuration Error", "The server is erroneously configured. Handler %s was requested, but not declared.", match->pat->childnm);
+           break;
+       }
+       if(childhandle(ch, req, fd, NULL, NULL))
+           childerror(req, fd);
+       break;
+    case HND_REPARSE:
+       match->pat->disable = 1;
+       serve(req, fd);
+       match->pat->disable = 0;
+       break;
+    default:
+       abort();
+    }
     freematch(match);
 }