Pinging this patch.
On Tue, 10 Oct 2017 21:31:20 -0700
Ori Bernstein <[email protected]> wrote:
> My website generator is a little stupid at times. It generates
> files with .html suffixes, but urls without them.
>
> I worked around this with some redirects, but it never felt
> quite right doing an extra round trip. Therefore, I added
> internal redirects, processing the rewrite before responding to
> an http request.
>
> This introduces new syntax to the config file, allowing you to
> do:
>
> location match "^(/foo/bar/[%w]+)$" {
> rewrite-to "/baz/%1.html"
> }
>
> Because we don't know what the paths should be relative
> to, all paths rewritten must be absolute.
>
> It seems like someone else may find it useful[1], so
> I'm submitting it. I've been running a slightly older
> version of this on https://myrlang.org for the last
> day or two, and it's been uneventful. The difference
> is that the syntax used to piggy back off the "block"
> action => 'block internal return 302 "path"'.
>
> This doesn't currently support chained rewrites. I think
> that it wouldn't be hard to add if it's needed.
>
> Ok?
>
> [1] https://github.com/reyk/httpd/issues/27
> ==========================================
>
>
> diff --git usr.sbin/httpd/config.c usr.sbin/httpd/config.c
> index 3c31c3d4cd3..7d2982af7b9 100644
> --- usr.sbin/httpd/config.c
> +++ usr.sbin/httpd/config.c
> @@ -448,7 +448,7 @@ config_getserver_config(struct httpd *env, struct server
> *srv,
> sizeof(srv_conf->errorlog));
> }
>
> - f = SRVFLAG_BLOCK|SRVFLAG_NO_BLOCK;
> + f = SRVFLAG_BLOCK|SRVFLAG_NO_BLOCK|SRVFLAG_REWRITE;
> if ((srv_conf->flags & f) == 0) {
> free(srv_conf->return_uri);
> srv_conf->flags |= parent->flags & f;
> diff --git usr.sbin/httpd/httpd.conf.5 usr.sbin/httpd/httpd.conf.5
> index a3c97629de3..3a00a750537 100644
> --- usr.sbin/httpd/httpd.conf.5
> +++ usr.sbin/httpd/httpd.conf.5
> @@ -454,6 +454,14 @@ instead of the log files.
> Disable any previous
> .Ic block
> in a location.
> +.It Ic rewrite-to Ar path
> +The current request path is rewritten to
> +.Ar path .
> +using the same macro expansions as
> +.Cm block return
> +rules. After macros are substituted, the resulting paths must be
> +absolute, beginning with a slash. Rewriting is not done
> +recursively.
> .It Ic root Ar option
> Configure the document root and options for the request path.
> Valid options are:
> diff --git usr.sbin/httpd/httpd.h usr.sbin/httpd/httpd.h
> index 05cbb8e3550..477115ec92d 100644
> --- usr.sbin/httpd/httpd.h
> +++ usr.sbin/httpd/httpd.h
> @@ -394,6 +394,7 @@ SPLAY_HEAD(client_tree, client);
> #define SRVFLAG_SERVER_MATCH 0x00200000
> #define SRVFLAG_SERVER_HSTS 0x00400000
> #define SRVFLAG_DEFAULT_TYPE 0x00800000
> +#define SRVFLAG_REWRITE 0x01000000
>
> #define SRVFLAG_BITS \
> "\10\01INDEX\02NO_INDEX\03AUTO_INDEX\04NO_AUTO_INDEX" \
> diff --git usr.sbin/httpd/parse.y usr.sbin/httpd/parse.y
> index fcf1938c42d..4072ee5b532 100644
> --- usr.sbin/httpd/parse.y
> +++ usr.sbin/httpd/parse.y
> @@ -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 REWRITE PASS
> %token <v.string> STRING
> %token <v.number> NUMBER
> %type <v.port> port
> @@ -986,6 +986,11 @@ filter : block RETURN NUMBER optstring {
> srv_conf->return_uri_len = strlen($4) + 1;
> }
> }
> + | REWRITE STRING {
> + srv_conf->flags |= SRVFLAG_REWRITE;
> + srv_conf->return_uri = $2;
> + srv_conf->return_uri_len = strlen($2) + 1;
> + }
> | block DROP {
> /* No return code, silently drop the connection */
> srv_conf->return_code = 0;
> @@ -1255,6 +1260,7 @@ lookup(char *s)
> { "request", REQUEST },
> { "requests", REQUESTS },
> { "return", RETURN },
> + { "rewrite-to", REWRITE },
> { "root", ROOT },
> { "sack", SACK },
> { "server", SERVER },
> diff --git usr.sbin/httpd/server_http.c usr.sbin/httpd/server_http.c
> index e64de0d2f9c..c9ea4771037 100644
> --- usr.sbin/httpd/server_http.c
> +++ usr.sbin/httpd/server_http.c
> @@ -1162,10 +1162,34 @@ server_expand_http(struct client *clt, const char
> *val, char *buf,
> return (buf);
> }
>
> +static int
> +server_set_path(struct http_descriptor *desc, char *input)
> +{
> + char path[PATH_MAX];
> +
> + if (input == NULL || url_decode(input) == NULL)
> + return -1;
> + if (canonicalize_path(input, path, sizeof(path)) == NULL)
> + return (-1);
> + free(desc->http_path);
> + if ((desc->http_path = strdup(path)) == NULL)
> + return(-1);
> + return (0);
> +}
> +
> +static int
> +server_rewrite(struct client *clt, struct http_descriptor *desc, char *input)
> +{
> + char path[PATH_MAX];
> +
> + if (server_expand_http(clt, input, path, sizeof(path)) == NULL)
> + return -1;
> + return (server_set_path(desc, path));
> +}
> +
> int
> server_response(struct httpd *httpd, struct client *clt)
> {
> - char path[PATH_MAX];
> char hostname[HOST_NAME_MAX+1];
> struct http_descriptor *desc = clt->clt_descreq;
> struct http_descriptor *resp = clt->clt_descresp;
> @@ -1178,12 +1202,7 @@ server_response(struct httpd *httpd, struct client
> *clt)
> const char *errstr = NULL;
>
> /* Canonicalize the request path */
> - if (desc->http_path == NULL ||
> - url_decode(desc->http_path) == NULL ||
> - canonicalize_path(desc->http_path, path, sizeof(path)) == NULL)
> - goto fail;
> - free(desc->http_path);
> - if ((desc->http_path = strdup(path)) == NULL)
> + if (server_set_path(desc, desc->http_path) == -1)
> goto fail;
>
> key.kv_key = "Host";
> @@ -1284,6 +1303,10 @@ server_response(struct httpd *httpd, struct client
> *clt)
> /* Now search for the location */
> srv_conf = server_getlocation(clt, desc->http_path);
>
> + /* If we have an internal redirection, rewrite the URL */
> + if (srv_conf->flags & SRVFLAG_REWRITE)
> + if (server_rewrite(clt, desc, srv_conf->return_uri) == -1)
> + goto fail;
> if (srv_conf->flags & SRVFLAG_BLOCK) {
> server_abort_http(clt, srv_conf->return_code,
> srv_conf->return_uri);
>
--
Ori Bernstein <[email protected]>