Thanks for supporting and rebasing the diff.

On 06.01.17 13:21, Atanas Vladimirov wrote:
On Mon, Dec 05, 2016 at 04:20:02PM +0200, Gregory Edigarov wrote:
Hello,

I know, it considered featuritis, but still, hey, it should go somewhere.
This diff is based on the diff sent here by Stanislav Adaszewski
(s.adaszev...@gmail.com),
some time ago.
I've added one option 'test', i.e.: pass rewrite [test] index.php?q=%1, so
it will not rewrite
if file or directory present, and a manual page section, describing the
rule.
For those like me, trying to stick with base as much as possible.

suggestions?

Hello,

The diff is malformed and cannot be applied.
The patch below is re-based against -current.
I exclude the httpd.conf example bits.
They can be added later as separate patch.

Index: httpd.conf.5
===================================================================
RCS file: /home/vlado/cvsync/cvsroot/src/usr.sbin/httpd/httpd.conf.5,v
retrieving revision 1.76
diff -u -p -r1.76 httpd.conf.5
--- httpd.conf.5        14 Nov 2016 10:28:31 -0000      1.76
+++ httpd.conf.5        6 Jan 2017 09:47:53 -0000
@@ -388,6 +388,8 @@ The pattern may contain captures that ca
  .Ar uri
  of an enclosed
  .Ic block return
+or
+.Ic pass rewrite
  option.
  .It Oo Ic no Oc Ic log Op Ar option
  Set the specified logging options.
@@ -446,6 +448,17 @@ instead of the log files.
  Disable any previous
  .Ic block
  in a location.
+.It Ic pass rewrite Oo Ic test Oc Ic Ar uri
+Disable any previous block in location, the path gets rewritten as
+specified in
+.Ic block return
+statement. If
+.Ic test
+option is present, the rewrite will
+.Em not
+happen if file or directory referenced by the
+.Ar uri
+present.
  .It Ic root Ar option
  Configure the document root and options for the request path.
  Valid options are:
Index: httpd.h
===================================================================
RCS file: /home/vlado/cvsync/cvsroot/src/usr.sbin/httpd/httpd.h,v
retrieving revision 1.124
diff -u -p -r1.124 httpd.h
--- httpd.h     17 Nov 2016 14:52:48 -0000      1.124
+++ httpd.h     6 Jan 2017 09:47:53 -0000
@@ -73,6 +73,7 @@
  #define SERVER_MAX_PREFETCH   256
  #define SERVER_MIN_PREFETCHED 32
  #define SERVER_HSTS_DEFAULT_AGE       31536000
+#define SERVER_MAX_RECUR_REWR  0
#define MEDIATYPE_NAMEMAX 128 /* file name extension */
  #define MEDIATYPE_TYPEMAX     64      /* length of type/subtype */
@@ -364,13 +365,15 @@ 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_TEST           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\31REWRITE\32TEST"
#define TCPFLAG_NODELAY 0x01
  #define TCPFLAG_NNODELAY      0x02
@@ -472,6 +475,7 @@ struct server_config {
        int                      return_code;
        char                    *return_uri;
        off_t                    return_uri_len;
+       char                     rewrite_uri[PATH_MAX];
int hsts_max_age;
        uint8_t                  hsts_flags;
Index: parse.y
===================================================================
RCS file: /home/vlado/cvsync/cvsroot/src/usr.sbin/httpd/parse.y,v
retrieving revision 1.87
diff -u -p -r1.87 parse.y
--- parse.y     5 Jan 2017 13:53:09 -0000       1.87
+++ parse.y     6 Jan 2017 09:47:53 -0000
@@ -134,7 +134,7 @@ typedef struct {
  %token        LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY OCSP ON PORT 
PREFORK
  %token        PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG 
TCP TIMEOUT
  %token        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 TEST
  %token        <v.string>        STRING
  %token  <v.number>      NUMBER
  %type <v.port>  port
@@ -971,6 +971,29 @@ filter             : block RETURN NUMBER optstring 
                        /* Forbidden */
                        srv_conf->return_code = 403;
                }
+               | PASS REWRITE STRING           {
+                       srv_conf->flags |= SRVFLAG_REWRITE;
+                       if (strlcpy(srv_conf->rewrite_uri, $3,
+                               sizeof(srv_conf->rewrite_uri)) >=
+                               sizeof(srv_conf->rewrite_uri)) {
+                               yyerror("url rewrite string too long");
+                               free($3);
+                               YYERROR;
+                       }
+                       free($3);
+               }
+               | PASS REWRITE TEST STRING    {
+                       srv_conf->flags |= SRVFLAG_REWRITE;
+                       srv_conf->flags |= SRVFLAG_TEST;
+                       if (strlcpy(srv_conf->rewrite_uri, $4,
+                               sizeof(srv_conf->rewrite_uri)) >=
+                               sizeof(srv_conf->rewrite_uri)) {
+                               yyerror("url rewrite string too long");
+                               free($4);
+                               YYERROR;
+                       }
+                       free($4);
+               }
                | PASS                          {
                        srv_conf->flags &= ~SRVFLAG_BLOCK;
                        srv_conf->flags |= SRVFLAG_NO_BLOCK;
@@ -1231,6 +1254,7 @@ lookup(char *s)
                { "request",          REQUEST },
                { "requests",         REQUESTS },
                { "return",           RETURN },
+               { "rewrite",          REWRITE },
                { "root",             ROOT },
                { "sack",             SACK },
                { "server",           SERVER },
@@ -1240,6 +1264,7 @@ lookup(char *s)
                { "subdomains",               SUBDOMAINS },
                { "syslog",           SYSLOG },
                { "tcp",              TCP },
+               { "test",             TEST },
                { "timeout",          TIMEOUT },
                { "tls",              TLS },
                { "type",             TYPE },
Index: server_http.c
===================================================================
RCS file: /home/vlado/cvsync/cvsroot/src/usr.sbin/httpd/server_http.c,v
retrieving revision 1.110
diff -u -p -r1.110 server_http.c
--- server_http.c       26 Aug 2016 10:46:39 -0000      1.110
+++ server_http.c       6 Jan 2017 09:47:53 -0000
@@ -20,6 +20,7 @@
  #include <sys/queue.h>
  #include <sys/socket.h>
  #include <sys/tree.h>
+#include <sys/stat.h>
#include <netinet/in.h>
  #include <arpa/inet.h>
@@ -1039,7 +1040,7 @@ server_expand_http(struct client *clt, c
  int
  server_response(struct httpd *httpd, struct client *clt)
  {
-       char                     path[PATH_MAX];
+       char                     path[PATH_MAX],d_path[PATH_MAX];
        char                     hostname[HOST_NAME_MAX+1];
        struct http_descriptor  *desc = clt->clt_descreq;
        struct http_descriptor  *resp = clt->clt_descresp;
@@ -1047,9 +1048,12 @@ server_response(struct httpd *httpd, str
        struct server_config    *srv_conf = &srv->srv_conf;
        struct kv               *kv, key, *host;
        struct str_find          sm;
+       struct stat              st;
        int                      portval = -1, ret;
        char                    *hostval;
        const char              *errstr = NULL;
+       char                     buf[IBUF_READ_SIZE];
+       int                      n;
/* Canonicalize the request path */
        if (desc->http_path == NULL ||
@@ -1154,6 +1158,75 @@ server_response(struct httpd *httpd, str
        /* Now search for the location */
        srv_conf = server_getlocation(clt, desc->http_path);
+ /* URL Rewriting logic */
+       DPRINTF("%s: URL Rewriting logic, flags: %08X, rewrite_uri: %s, "
+               "http_path: %s\n", __func__, srv_conf->flags,
+               srv_conf->rewrite_uri, desc->http_path);
+       for (n = 0; srv_conf->flags & SRVFLAG_REWRITE; n++) {
+               if (n > SERVER_MAX_RECUR_REWR) {
+                       server_abort_http(clt, 500, "recursive "
+                       "rewrite limit exceeded");
+                       return (-1);
+               }
+               if (srv_conf->flags & SRVFLAG_TEST) {
+                       snprintf(d_path,PATH_MAX,"%s%s",srv_conf->root,path);
+                       if (stat(d_path,&st)) {
+                               DPRINTF("%s: Rewrite test from: %s to %s, n: 
%d\n",
+                                  __func__, desc->http_path, 
srv_conf->rewrite_uri, n);
+                               if (server_expand_http(clt, 
srv_conf->rewrite_uri, buf,
+                                  sizeof(buf)) == NULL) {
+                                       server_abort_http(clt, 500, 
strerror(errno));
+                                       return (-1);
+                               }
+                               if (desc->http_path != NULL) {
+                                       free(desc->http_path);
+                                       desc->http_path = NULL;
+                               }
+                               desc->http_path = strdup(buf);
+                               if (desc->http_path == NULL) {
+                                       server_abort_http(clt, 500, 
strerror(errno));
+                                       return (-1);
+                               }
+                               desc->http_query = strchr(desc->http_path, '?');
+                               if (desc->http_query != NULL) {
+                                       *desc->http_query++ = '\0';
+                                       desc->http_query = 
strdup(desc->http_query);
+                                       if (desc->http_query == NULL) {
+                                               server_abort_http(clt, 500, 
strerror(errno));
+                                       }
+                               }
+                       srv_conf = server_getlocation(clt, desc->http_path);
+                       }
+                       else break;
+               } else {
+                       DPRINTF("%s: Rewrite from: %s to %s, n: %d\n", __func__,
+                          desc->http_path, srv_conf->rewrite_uri, n);
+                       if (server_expand_http(clt, srv_conf->rewrite_uri, buf,
+                          sizeof(buf)) == NULL) {
+                               server_abort_http(clt, 500, strerror(errno));
+                               return (-1);
+                       }
+                       if (desc->http_path != NULL) {
+                               free(desc->http_path);
+                               desc->http_path = NULL;
+                       }
+                       desc->http_path = strdup(buf);
+                       if (desc->http_path == NULL) {
+                               server_abort_http(clt, 500, strerror(errno));
+                               return (-1);
+                       }
+                       desc->http_query = strchr(desc->http_path, '?');
+                       if (desc->http_query != NULL) {
+                               *desc->http_query++ = '\0';
+                               desc->http_query = strdup(desc->http_query);
+                               if (desc->http_query == NULL) {
+                                       server_abort_http(clt, 500, 
strerror(errno));
+                               }
+                       }
+                       srv_conf = server_getlocation(clt, desc->http_path);
+               }
+       }
+
        if (srv_conf->flags & SRVFLAG_BLOCK) {
                server_abort_http(clt, srv_conf->return_code,
                    srv_conf->return_uri);
@@ -1196,8 +1269,10 @@ server_getlocation(struct client *clt, c
        TAILQ_FOREACH(location, &srv->srv_hosts, entry) {
  #ifdef DEBUG
                if (location->flags & SRVFLAG_LOCATION) {
-                       DPRINTF("%s: location \"%s\" path \"%s\"",
-                           __func__, location->location, path);
+                       DPRINTF("%s: location \"%s\" path \"%s\" flags: %08X "
+                          "rewrite_uri: %s",
+                          __func__, location->location, path, location->flags,
+                          location->rewrite_uri);
                }
  #endif
                if ((location->flags & SRVFLAG_LOCATION) &&



Reply via email to