On Tue, May 29, 2018 at 06:48:31PM +0200, Reyk Floeter wrote: > Hi, > > it's about time. > > server "default" { > listen on * port 80 > location match "/de/(.*)" { > request rewrite "/ch/%1" > } > } > > You can also you the macros as in the "block return" external > redirects. So maybe something like: > > server "default" { > listen on * port 80 > location match "/(.*)" { > request rewrite "/$HTTP_HOST/%1" > } > } >
The syntax looks clear in my opinion. Would it be a good idea in your opinion to have request path rewriting in relayd also? For example to rewrite the request path for the (internal) application? For example for the url: "http://somesite.org/gopherproxy" to rewrite the path "/gopherproxy" to "/" for the application? in Nginx my current rule is like: location /gopherproxy/ { rewrite /gopherproxy/(.*) /$1 break; proxy_pass http://127.0.0.1:6969/; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass_header Server; } I have read the man page and relayd source-code, but have not found a way to replace part of the pattern in the path (only a fixed string with "set"). > Tests? OK? > > Please note that this diff intentionally breaks the "root strip" > option because it changes the grammar to "request strip". "root > strip" was semantically wrong but we didn't have a better place to put > it. An current.html entry can be made for the required grammar change. > > 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 29 May 2018 16:35:29 -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.95 > diff -u -p -u -p -r1.95 httpd.conf.5 > --- usr.sbin/httpd/httpd.conf.5 23 May 2018 19:02:50 -0000 1.95 > +++ usr.sbin/httpd/httpd.conf.5 29 May 2018 16:35:29 -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. > @@ -458,12 +460,31 @@ instead of the log files. > Disable any previous > .Ic block > in a location. > -.It Ic root Ar option > -Configure the document root and options for the request path. > +.It Ic request Ar option > +Configure the options for the request path. > Valid options are: > .Bl -tag -width Ds > -.It Ar directory > -Set the document root of the server. > +.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 > +path components from the beginning of the request path before looking > +up the stripped-down path at the document root. > +.El > +.It Ic root Ar directory > +Configure the document root of the server. > The > .Ar directory > is a pathname within the > @@ -472,12 +493,6 @@ root directory of > .Nm httpd . > If not specified, it defaults to > .Pa /htdocs . > -.It Ic strip Ar number > -Strip > -.Ar number > -path components from the beginning of the request path before looking > -up the stripped-down path at the document root. > -.El > .It Ic tcp Ar option > Enable or disable the specified TCP/IP options; see > .Xr tcp 4 > @@ -715,6 +730,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 29 May 2018 16:35:30 -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.99 > diff -u -p -u -p -r1.99 parse.y > --- usr.sbin/httpd/parse.y 23 May 2018 19:11:48 -0000 1.99 > +++ usr.sbin/httpd/parse.y 29 May 2018 16:35:31 -0000 > @@ -134,7 +134,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 > @@ -486,6 +486,7 @@ serveroptsl : LISTEN ON STRING opttls po > YYERROR; > } > } > + | request > | root > | directory > | logformat > @@ -804,7 +805,33 @@ rootflags : STRING { > free($1); > srv->srv_conf.flags |= SRVFLAG_ROOT; > } > - | STRIP NUMBER { > + ; > + > +request : REQUEST requestflags > + | REQUEST '{' optnl requestflags_l '}' > + ; > + > +requestflags_l : requestflags optcommanl requestflags_l > + | requestflags optnl > + ; > + > +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; > @@ -1261,6 +1288,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.119 > diff -u -p -u -p -r1.119 server_http.c > --- usr.sbin/httpd/server_http.c 6 Apr 2018 13:02:07 -0000 1.119 > +++ usr.sbin/httpd/server_http.c 29 May 2018 16:35:31 -0000 > @@ -1180,10 +1180,13 @@ server_response(struct httpd *httpd, str > char *hostval; > 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) > @@ -1286,6 +1289,28 @@ 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) { > + if (server_expand_http(clt, srv_conf->path, > + path, sizeof(path)) == NULL) > + goto fail; > + > + /* Canonicalize the updated request path */ > + if (canonicalize_path(path, > + path, sizeof(path)) == NULL) > + goto fail; > + > + log_debug("%s: rewrote %s -> %s", __func__, > + desc->http_path, path); > + > + 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, > -- Kind regards, Hiltjo