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,
--