ProxyPassReverse を RewriteRule のオプションにするパッチ

なんか https + リバースプロキシで subversion 使っていたら COPY メソッドでこけて 502 Bad Gateway になってなんじゃこれはとあれこれしているうちにできたパッチ (against httpd-2.2.4)。

ProxyPassReverse でできるよ、というのは半分正解。RewriteRule は perdir コンテキストだが ProxyPassReverse は vhost dir (訂正: 2007/10/01) コンテキストだ。RewriteRule に [P] オプションを指定して便利なのってやはり .htaccess に書けるというところだと思う。

使いかたは PR オプションを RewriteRule に指定してください。[P,PR] みたく。

diff -ur httpd-2.2.4.orig/modules/mappers/mod_rewrite.c httpd-2.2.4/modules/mappers/mod_rewrite.c
--- httpd-2.2.4.orig/modules/mappers/mod_rewrite.c	2006-09-15 22:19:25.000000000 +0900
+++ httpd-2.2.4/modules/mappers/mod_rewrite.c	2007-07-16 09:23:40.000000000 +0900
@@ -145,6 +145,7 @@
 #define RULEFLAG_NOESCAPE           1<<11
 #define RULEFLAG_NOSUB              1<<12
 #define RULEFLAG_STATUS             1<<13
+#define RULEFLAG_PROXYREVERSE       1<<14
 
 /* return code of the rewrite rule
  * the result may be escaped - or not
@@ -746,7 +747,7 @@
 /*
  * strip 'http[s]://ourhost/' from URI
  */
-static void reduce_uri(request_rec *r)
+static int reduce_uri(request_rec *r)
 {
     char *cp;
     apr_size_t l;
@@ -799,10 +800,11 @@
         if (ap_matches_request_vhost(r, host, port)) {
             rewritelog((r, 3, NULL, "reduce %s -> %s", r->filename, url));
             r->filename = apr_pstrdup(r->pool, url);
+            return 1;
         }
     }
 
-    return;
+    return 0;
 }
 
 /*
@@ -3278,6 +3280,10 @@
             || !strcasecmp(key, "assthrough")) {           /* passthrough */
             cfg->flags |= RULEFLAG_PASSTHROUGH;
         }
+        else if (((*key == 'R' || *key == 'r') && !key[1])
+            || !strcasecmp(key, "roxyReverse")) {
+            cfg->flags |= RULEFLAG_PROXYREVERSE;
+        } 
         else {
             ++error;
         }
@@ -3811,6 +3817,43 @@
         rewritelog((r, 2, ctx->perdir, "forcing proxy-throughput with %s",
                     r->filename));
 
+        if (p->flags & RULEFLAG_PROXYREVERSE) {
+            static const char *transform_hdrs[] = {
+                "Location",
+                "Content-Location",
+                "URI",
+                "Destination",
+                "Set-Cookie",
+                NULL
+            };
+            int i ;
+            rewrite_ctx _ctx = *ctx;
+            request_rec _r = *_ctx.r;
+            _r.path_info = NULL;
+            _ctx.r = &_r;
+
+            for (i = 0; transform_hdrs[i]; ++i) {
+                const char *val = apr_table_get(ctx->r->headers_in,
+                                                transform_hdrs[i]);
+                if (!val)
+                    continue;
+                _r.filename = (char *)val;
+                if (reduce_uri(&_r) && ctx->perdir) {
+                    apr_size_t rlen = strlen(ctx->uri), alen = strlen(r->uri);
+                    if (alen > rlen)
+                        _r.filename += alen - rlen;
+                }
+                p->flags &= ~RULEFLAG_PROXYREVERSE;
+                if (apply_rewrite_rule(p, &_ctx))
+                    rewritelog((r, 2, ctx->perdir,
+                                "rewrite location header %s: %s -> %s",
+                                transform_hdrs[i], val, _r.filename));
+                p->flags |= RULEFLAG_PROXYREVERSE;
+                apr_table_setn(ctx->r->headers_in, transform_hdrs[i],
+                               _r.filename);
+            }
+        }
+
         r->filename = apr_pstrcat(r->pool, "proxy:", r->filename, NULL);
         return 1;
     }

http://voltex.jp/patches/mod_rewrite_proxy_reverse-20070716.patch.diff.gz