Pinging this patch.

On Tue, 10 Oct 2017 21:31:20 -0700
Ori Bernstein <o...@eigenstate.org> 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 <o...@eigenstate.org>

Reply via email to