I have the following setup: a request comes in to my server, and depending on what the URI looks like, I redirect the request (using RewriteRules) to another location, where more rewriting takes place, additional access checks are performed, and finally the request is proxied (again using RewriteRules) to another web server.
The problem is that when a request comes in with an escaped special character, such as '#' (%23), the first RewriteRule unescapes it and passes it along. The next RewriteRule receives the URI with the fragment chopped off, thus resulting in an incorrect request. I could not find an option in documentation or in the code that would prevent this from happening; so I fixed the problem myself (the patch against 2.0.45 is attached at the end of this message). The way I fixed it is quite possibly silly, but I just needed it done fast. I'd like to hear some suggestions about how I can either a). write a better fix or b). use a different approach to this. Thanks, - Dmitri. What the patch does: a new option, [ESC], can be added at the end of RewriteRule, and when it's set, the URI is escaped before any rewriting takes place. =================================================================== RCS file: /cvsroot/ThirdParty/apache2/modules/mappers/mod_rewrite.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- mod_rewrite.c 2003/04/10 19:09:56 1.1.1.2 +++ mod_rewrite.c 2003/06/01 19:49:19 1.2 @@ -958,6 +958,10 @@ || strcasecmp(key, "NC") == 0 ) { cfg->flags |= RULEFLAG_NOCASE; } + else if ( strcasecmp(key, "escape") == 0 + || strcasecmp(key, "ESC") == 0 ) { + cfg->flags |= RULEFLAG_ESCAPE; + } else { return apr_pstrcat(p, "RewriteRule: unknown flag '", key, "'", NULL); } @@ -1833,6 +1837,9 @@ continue; } + if (p->flags & RULEFLAG_ESCAPE) + r->filename = ap_escape_uri(r->pool, r->filename); + /* * Apply the current rule. */ @@ -2171,7 +2178,7 @@ * an on-the-fly generated QUERY_STRING part into r->args */ r->filename = apr_pstrdup(r->pool, newuri); - splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND); + splitout_queryargs(r, p->flags); /* * Add the previously stripped per-directory location @@ -2203,6 +2210,8 @@ rewritelog(r, 2, "[per-dir %s] forcing proxy-throughput with %s", perdir, r->filename); } + if (p->flags & RULEFLAG_ESCAPE) + r->filename = ap_escape_uri(r->pool, r->filename); r->filename = apr_pstrcat(r->pool, "proxy:", r->filename, NULL); return 1; } @@ -2619,7 +2628,7 @@ ** */ -static void splitout_queryargs(request_rec *r, int qsappend) +static void splitout_queryargs(request_rec *r, int flags) { char *q; char *olduri; @@ -2627,8 +2636,9 @@ q = strchr(r->filename, '?'); if (q != NULL) { olduri = apr_pstrdup(r->pool, r->filename); - *q++ = '\0'; - if (qsappend) { + if (!(flags & RULEFLAG_ESCAPE)) + *q++ = '\0'; + if (flags & RULEFLAG_QSAPPEND) { r->args = apr_pstrcat(r->pool, q, "&", r->args, NULL); } else { Index: mod_rewrite.h =================================================================== RCS file: /cvsroot/ThirdParty/apache2/modules/mappers/mod_rewrite.h,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- mod_rewrite.h 2003/04/10 19:09:56 1.1.1.2 +++ mod_rewrite.h 2003/06/01 19:49:19 1.2 @@ -165,6 +165,7 @@ #define RULEFLAG_QSAPPEND 1<<11 #define RULEFLAG_NOCASE 1<<12 #define RULEFLAG_NOESCAPE 1<<13 +#define RULEFLAG_ESCAPE 1<<14 #define ACTION_NORMAL 1<<0 #define ACTION_NOESCAPE 1<<1 @@ -410,7 +411,7 @@ backrefinfo *briRR, backrefinfo *briRC); /* URI transformation function */ -static void splitout_queryargs(request_rec *r, int qsappend); +static void splitout_queryargs(request_rec *r, int flags); static void fully_qualify_uri(request_rec *r); static void reduce_uri(request_rec *r); static int is_absolute_uri(char *uri);