Hello,

I'm a newbie apache coder, so I apologize in advance for any mistake or
oversight :-)

I've coded this small patch to avoid the ugly hack of having to write
rules such as

RewriteRule .* /index.cgi? 

to tell mod_rewrite "forget the QS" and thus provide greater consistency
in the flags "API".

It's fairly unintrusive and it's working AFAICT. 

Please tell if you think it's worth it and that it works in your
particular rewrite setup. I marked with XXX: some doubts and TODO items
so please clarify those for me to fix, if interested.

I attach the patch against trunk, the docs patch, and a simple test
case.

Regards,
V.
Index: docs/manual/mod/mod_rewrite.xml
===================================================================
--- docs/manual/mod/mod_rewrite.xml	(revision 493509)
+++ docs/manual/mod/mod_rewrite.xml	(working copy)
@@ -1392,6 +1392,15 @@
         instead of replacing it. Use this when you want to add more
         data to the query string via a rewrite rule.</li>
 
+        <li>'<strong><code>qsremove|QSR</code></strong>'
+        (<strong>q</strong>uery <strong>s</strong>tring
+        <strong>r</strong>emove)<br />
+        This flag forces the rewrite engine to avoid writing a
+	query string in the destination URL. This flag eliminates the need for
+	the workaround of adding a single '?' at the end of an URL in the 
+	RewriteRule to remove a query string. When both the QSA and the QSR 
+	flags are specified, QSA is ignored and no warning is raised.</li>
+
          <li>'<strong><code>redirect|R</code>
           [=<em>code</em>]</strong>' (force <a id="redirect"
           name="redirect"><strong>r</strong>edirect</a>)<br />
Index: modules/mappers/mod_rewrite.c
===================================================================
--- modules/mappers/mod_rewrite.c	(revision 493509)
+++ modules/mappers/mod_rewrite.c	(working copy)
@@ -150,6 +150,7 @@
 #define RULEFLAG_NOESCAPE           1<<11
 #define RULEFLAG_NOSUB              1<<12
 #define RULEFLAG_STATUS             1<<13
+#define RULEFLAG_QSREMOVE           1<<14
 
 /* return code of the rewrite rule
  * the result may be escaped - or not
@@ -709,7 +710,7 @@
  * split out a QUERY_STRING part from
  * the current URI string
  */
-static void splitout_queryargs(request_rec *r, int qsappend)
+static void splitout_queryargs(request_rec *r, int qsappend, int qsremove)
 {
     char *q;
 
@@ -732,23 +733,35 @@
 
         olduri = apr_pstrdup(r->pool, r->filename);
         *q++ = '\0';
-        if (qsappend) {
-            r->args = apr_pstrcat(r->pool, q, "&", r->args, NULL);
-        }
-        else {
-            r->args = apr_pstrdup(r->pool, q);
-        }
+	if (qsremove) {
+		r->args = NULL;
+	} else {
+		if (qsappend) {
+		    r->args = apr_pstrcat(r->pool, q, "&", r->args, NULL);
+		}
+		else {
+		    r->args = apr_pstrdup(r->pool, q);
+		}
 
-        len = strlen(r->args);
-        if (!len) {
-            r->args = NULL;
-        }
-        else if (r->args[len-1] == '&') {
-            r->args[len-1] = '\0';
-        }
-
-        rewritelog((r, 3, NULL, "split uri=%s -> uri=%s, args=%s", olduri,
+		len = strlen(r->args);
+		if (!len) {
+		    r->args = NULL;
+		}
+		else if (r->args[len-1] == '&') {
+		    r->args[len-1] = '\0';
+		}
+	}
+        rewritelog((r, 3, NULL, "split uri=%s -> uri=%s, args=%s %s", olduri,
+                    r->filename, r->args ? r->args : "<none>", qsremove ? "(QS remove requested)" : ""));
+    } else {
+        if (qsremove) {
+		r->args = NULL;
+		/* XXX: This is for the log only, probably not really necessary */
+        	char *olduri;
+        	olduri = apr_pstrdup(r->pool, r->filename);
+        	rewritelog((r, 3, NULL, "split uri=%s -> uri=%s, args=%s (QS remove requested)", olduri,
                     r->filename, r->args ? r->args : "<none>"));
+	}
     }
 
     return;
@@ -3407,6 +3420,18 @@
 
     case 'q':
     case 'Q':
+        if (   !strcasecmp(key, "SR")
+            || !strcasecmp(key, "sremove")) {              /* qsremove */
+		cfg->flags |= RULEFLAG_QSREMOVE;
+		/*if (cfg->flags & RULEFLAG_QSAPPEND) {*/
+			/* XXX: report a warning about incompatibility. It's not as if
+			 * something bad will happen, it's just to avoid unpleasant 
+			 * surprises. QSRemove takes precedence over QSAppend 
+			 * in splitout_queryargs(). It isn't done as I can't call
+			 * rewritelog here!, and returning something means a fatal error.
+			 * Don't know where to fix. */
+		/*}*/
+	} else 
         if (   !strcasecmp(key, "SA")
             || !strcasecmp(key, "sappend")) {              /* qsappend */
             cfg->flags |= RULEFLAG_QSAPPEND;
@@ -3906,7 +3931,7 @@
 
     /* Now adjust API's knowledge about r->filename and r->args */
     r->filename = newuri;
-    splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND);
+    splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND, p->flags & RULEFLAG_QSREMOVE);
 
     /* Add the previously stripped per-directory location prefix, unless
      * (1) it's an absolute URL path and
RewriteEngine On
RewriteCond %{REQUEST_URI} !test-cgi
RewriteRule .*1 http://%{SERVER_NAME}:%{SERVER_PORT}/cgi-bin/test-cgi [L,QSR]
RewriteCond %{REQUEST_URI} !test-cgi2
RewriteRule .*2 http://%{SERVER_NAME}:%{SERVER_PORT}/cgi-bin/test-cgi2 [L,QSA]
RewriteCond %{REQUEST_URI} !test-cgi3
RewriteRule .*3 http://%{SERVER_NAME}:%{SERVER_PORT}/cgi-bin/test-cgi3?foo=bar 
[L,QSR]
RewriteCond %{REQUEST_URI} !test-cgi4
RewriteRule .*4 http://%{SERVER_NAME}:%{SERVER_PORT}/cgi-bin/test-cgi4?foo=bar 
[L,QSA]
RewriteCond %{REQUEST_URI} !test-cgi5
RewriteRule .*5 http://%{SERVER_NAME}:%{SERVER_PORT}/cgi-bin/test-cgi5?foo=bar 
[L]
RewriteCond %{REQUEST_URI} !test-cgi6
RewriteRule .*6 http://%{SERVER_NAME}:%{SERVER_PORT}/cgi-bin/test-cgi6 [L]

RewriteLog /usr/local/apache2/logs/rewrite_log
RewriteLogLevel 9

Attachment: test.sh
Description: application/shellscript

Reply via email to