From: Fredrik Tolf Date: Sat, 17 Jul 2021 23:31:38 +0000 (+0200) Subject: patplex: Add reparse action. X-Git-Url: http://www.dolda2000.com/gitweb/?p=ashd.git;a=commitdiff_plain;h=597edd91dd69eece8ef716e8113d3e2cc4d03d37 patplex: Add reparse action. --- diff --git a/doc/patplex.doc b/doc/patplex.doc index 5a60e96..a9ebe69 100644 --- a/doc/patplex.doc +++ b/doc/patplex.doc @@ -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: diff --git a/src/patplex.c b/src/patplex.c index f76cc72..e893bc0 100644 --- a/src/patplex.c +++ b/src/patplex.c @@ -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); }