Hi Reyk, I have tested your patch against -current httpd and it works well on my setup.
Mischa On 20 Jun at 16:41, Reyk Floeter <[email protected]> wrote: > anyone? > > On Wed, Jun 13, 2018 at 05:20:55PM +0200, Reyk Floeter wrote: > > On Wed, May 30, 2018 at 12:36:05AM +0200, Reyk Floeter wrote: > > > as mentioned in the big diff before, this implements rewrites. This > > > diff applies on top of the previous ones. > > > > > > Implement the "request rewrite" option for internal rewrites. > > > > > > For example: > > > > > > location match "/page/(%d+)/.*" { > > > request rewrite > > > "/static/index.php?id=%1&$QUERY_STRING" > > > } > > > > > > Please note that httpd uses patterns(7) and not regex. > > > > > > > Same, diff, re-applied on top of the previous commits. > > > > OK? > > > > Reyk > > > > Index: usr.sbin/httpd/config.c > > =================================================================== > > RCS file: /cvs/src/usr.sbin/httpd/config.c,v > > retrieving revision 1.54 > > diff -u -p -u -p -r1.54 config.c > > --- usr.sbin/httpd/config.c 19 May 2018 13:56:56 -0000 1.54 > > +++ usr.sbin/httpd/config.c 13 Jun 2018 15:18:24 -0000 > > @@ -476,6 +476,13 @@ config_getserver_config(struct httpd *en > > &parent->default_type, sizeof(struct media_type)); > > } > > > > + f = SRVFLAG_PATH_REWRITE|SRVFLAG_NO_PATH_REWRITE; > > + if ((srv_conf->flags & f) == 0) { > > + srv_conf->flags |= parent->flags & f; > > + (void)strlcpy(srv_conf->path, parent->path, > > + sizeof(srv_conf->path)); > > + } > > + > > f = SRVFLAG_SERVER_HSTS; > > srv_conf->flags |= parent->flags & f; > > srv_conf->hsts_max_age = parent->hsts_max_age; > > Index: usr.sbin/httpd/httpd.conf.5 > > =================================================================== > > RCS file: /cvs/src/usr.sbin/httpd/httpd.conf.5,v > > retrieving revision 1.97 > > diff -u -p -u -p -r1.97 httpd.conf.5 > > --- usr.sbin/httpd/httpd.conf.5 13 Jun 2018 15:08:24 -0000 1.97 > > +++ usr.sbin/httpd/httpd.conf.5 13 Jun 2018 15:18:25 -0000 > > @@ -198,6 +198,8 @@ argument can be used with return codes i > > .Sq Location: > > header for redirection to a specified URI. > > .Pp > > +It is possible to rewrite the request to redirect it to a different > > +external location. > > The > > .Ar uri > > may contain predefined macros that will be expanded at runtime: > > @@ -396,10 +398,10 @@ the > > using pattern matching instead of shell globbing rules, > > see > > .Xr patterns 7 . > > -The pattern may contain captures that can be used in the > > -.Ar uri > > -of an enclosed > > +The pattern may contain captures that can be used in an enclosed > > .Ic block return > > +or > > +.Ic request rewrite > > option. > > .It Oo Ic no Oc Ic log Op Ar option > > Set the specified logging options. > > @@ -462,6 +464,19 @@ in a location. > > Configure the options for the request path. > > Valid options are: > > .Bl -tag -width Ds > > +.It Oo Ic no Oc Ic rewrite Ar path > > +Enable or disable rewriting of the request. > > +Unlike the redirection with > > +.Ic block return , > > +this will change the request path internally before > > +.Nm httpd > > +makes a final decision about the matching location. > > +The > > +.Ar path > > +argument may contain predefined macros that will be expanded at runtime. > > +See the > > +.Ic block return > > +option for the list of supported macros. > > .It Ic strip Ar number > > Strip > > .Ar number > > @@ -721,6 +736,17 @@ server "example.com" { > > > > server "www.example.com" { > > listen on 10.0.0.1 port 80 > > +} > > +.Ed > > +The request can also be rewritten with the > > +.Ic request rewrite > > +directive: > > +.Bd -literal -offset indent > > +server "example.com" { > > + listen on * port 80 > > + location match "/old/(.*)" { > > + request rewrite "/new/%1" > > + } > > } > > .Ed > > .Sh SEE ALSO > > Index: usr.sbin/httpd/httpd.h > > =================================================================== > > RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v > > retrieving revision 1.137 > > diff -u -p -u -p -r1.137 httpd.h > > --- usr.sbin/httpd/httpd.h 19 May 2018 13:56:56 -0000 1.137 > > +++ usr.sbin/httpd/httpd.h 13 Jun 2018 15:18:25 -0000 > > @@ -398,13 +398,15 @@ SPLAY_HEAD(client_tree, client); > > #define SRVFLAG_SERVER_MATCH 0x00200000 > > #define SRVFLAG_SERVER_HSTS 0x00400000 > > #define SRVFLAG_DEFAULT_TYPE 0x00800000 > > +#define SRVFLAG_PATH_REWRITE 0x01000000 > > +#define SRVFLAG_NO_PATH_REWRITE 0x02000000 > > > > #define SRVFLAG_BITS > > \ > > "\10\01INDEX\02NO_INDEX\03AUTO_INDEX\04NO_AUTO_INDEX" \ > > "\05ROOT\06LOCATION\07FCGI\10NO_FCGI\11LOG\12NO_LOG\13SOCKET" \ > > "\14SYSLOG\15NO_SYSLOG\16TLS\17ACCESS_LOG\20ERROR_LOG" \ > > "\21AUTH\22NO_AUTH\23BLOCK\24NO_BLOCK\25LOCATION_MATCH" \ > > - "\26SERVER_MATCH\27SERVER_HSTS\30DEFAULT_TYPE" > > + "\26SERVER_MATCH\27SERVER_HSTS\30DEFAULT_TYPE\31PATH\32NO_PATH" > > > > #define TCPFLAG_NODELAY 0x01 > > #define TCPFLAG_NNODELAY 0x02 > > @@ -470,8 +472,9 @@ struct server_config { > > uint32_t parent_id; > > char name[HOST_NAME_MAX+1]; > > char location[HTTPD_LOCATION_MAX]; > > - char index[PATH_MAX]; > > char root[PATH_MAX]; > > + char path[PATH_MAX]; > > + char index[PATH_MAX]; > > char socket[PATH_MAX]; > > char accesslog[PATH_MAX]; > > char errorlog[PATH_MAX]; > > Index: usr.sbin/httpd/parse.y > > =================================================================== > > RCS file: /cvs/src/usr.sbin/httpd/parse.y,v > > retrieving revision 1.102 > > diff -u -p -u -p -r1.102 parse.y > > --- usr.sbin/httpd/parse.y 13 Jun 2018 15:08:24 -0000 1.102 > > +++ usr.sbin/httpd/parse.y 13 Jun 2018 15:18:25 -0000 > > @@ -139,7 +139,7 @@ typedef struct { > > %token LISTEN LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY OCSP ON > > PORT PREFORK > > %token PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG > > TCP TICKET > > %token TIMEOUT TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD > > REQUEST > > -%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS > > +%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS REWRITE > > %token CA CLIENT CRL OPTIONAL > > %token <v.string> STRING > > %token <v.number> NUMBER > > @@ -820,7 +820,23 @@ requestflags_l : requestflags optcommanl > > | requestflags optnl > > ; > > > > -requestflags : STRIP NUMBER { > > +requestflags : REWRITE STRING { > > + if (strlcpy(srv->srv_conf.path, $2, > > + sizeof(srv->srv_conf.path)) >= > > + sizeof(srv->srv_conf.path)) { > > + yyerror("request path too long"); > > + free($2); > > + YYERROR; > > + } > > + free($2); > > + srv->srv_conf.flags |= SRVFLAG_PATH_REWRITE; > > + srv->srv_conf.flags &= ~SRVFLAG_NO_PATH_REWRITE; > > + } > > + | NO REWRITE { > > + srv->srv_conf.flags |= SRVFLAG_NO_PATH_REWRITE; > > + srv->srv_conf.flags &= ~SRVFLAG_PATH_REWRITE; > > + } > > + | STRIP NUMBER { > > if ($2 < 0 || $2 > INT_MAX) { > > yyerror("invalid strip number"); > > YYERROR; > > @@ -1277,6 +1293,7 @@ lookup(char *s) > > { "request", REQUEST }, > > { "requests", REQUESTS }, > > { "return", RETURN }, > > + { "rewrite", REWRITE }, > > { "root", ROOT }, > > { "sack", SACK }, > > { "server", SERVER }, > > Index: usr.sbin/httpd/server_http.c > > =================================================================== > > RCS file: /cvs/src/usr.sbin/httpd/server_http.c,v > > retrieving revision 1.120 > > diff -u -p -u -p -r1.120 server_http.c > > --- usr.sbin/httpd/server_http.c 11 Jun 2018 12:12:51 -0000 1.120 > > +++ usr.sbin/httpd/server_http.c 13 Jun 2018 15:18:25 -0000 > > @@ -1,7 +1,7 @@ > > /* $OpenBSD: server_http.c,v 1.120 2018/06/11 12:12:51 reyk Exp $ */ > > > > /* > > - * Copyright (c) 2006 - 2017 Reyk Floeter <[email protected]> > > + * Copyright (c) 2006 - 2018 Reyk Floeter <[email protected]> > > * > > * Permission to use, copy, modify, and distribute this software for any > > * purpose with or without fee is hereby granted, provided that the above > > @@ -1170,13 +1170,16 @@ server_response(struct httpd *httpd, str > > struct kv *kv, key, *host; > > struct str_find sm; > > int portval = -1, ret; > > - char *hostval; > > + char *hostval, *query; > > const char *errstr = NULL; > > > > - /* Canonicalize the request path */ > > + /* Decode the URL */ > > if (desc->http_path == NULL || > > - url_decode(desc->http_path) == NULL || > > - canonicalize_path(desc->http_path, path, sizeof(path)) == NULL) > > + url_decode(desc->http_path) == NULL) > > + goto fail; > > + > > + /* Canonicalize the request path */ > > + if (canonicalize_path(desc->http_path, path, sizeof(path)) == NULL) > > goto fail; > > free(desc->http_path); > > if ((desc->http_path = strdup(path)) == NULL) > > @@ -1279,6 +1282,42 @@ server_response(struct httpd *httpd, str > > > > /* Now search for the location */ > > srv_conf = server_getlocation(clt, desc->http_path); > > + > > + /* Optional rewrite */ > > + if (srv_conf->flags & SRVFLAG_PATH_REWRITE) { > > + /* Expand macros */ > > + if (server_expand_http(clt, srv_conf->path, > > + path, sizeof(path)) == NULL) > > + goto fail; > > + > > + /* > > + * Reset and update the query. The updated query must already > > + * be URL encoded - either specified by the user or by using the > > + * original $QUERY_STRING. > > + */ > > + free(desc->http_query); > > + desc->http_query = NULL; > > + if ((query = strchr(path, '?')) != NULL) { > > + *query++ = '\0'; > > + if ((desc->http_query = strdup(query)) == NULL) > > + goto fail; > > + } > > + > > + /* Canonicalize the updated request path */ > > + if (canonicalize_path(path, > > + path, sizeof(path)) == NULL) > > + goto fail; > > + > > + log_debug("%s: rewrote %s -> %s?%s", __func__, > > + desc->http_path, path, desc->http_query); > > + > > + free(desc->http_path); > > + if ((desc->http_path = strdup(path)) == NULL) > > + goto fail; > > + > > + /* Now search for the updated location */ > > + srv_conf = server_getlocation(clt, desc->http_path); > > + } > > > > if (srv_conf->flags & SRVFLAG_BLOCK) { > > server_abort_http(clt, srv_conf->return_code, > > -- >
