homepage Welcome to WebmasterWorld Guest from
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Visit PubCon.com
Home / Forums Index / Code, Content, and Presentation / Apache Web Server
Forum Library, Charter, Moderators: Ocean10000 & incrediBILL & phranque

Apache Web Server Forum

Redirect all Query Strings except zoneid
redirect, rewriterule, htaccess, rewritecond

 7:28 pm on Mar 30, 2013 (gmt 0)

I have a couple of questions. One, how can I redirect all URLs that contain query strings to the URL without the query string except for ones that have zoneid, which is used by OpenX? I tried using the following but it doesn't work:

RewriteCond %{QUERY_STRING} !zoneid
RewriteRule (.*) http://www.example.com/$1? [R=301]

Second, is there a way to set up the RewriteRule so that I can just add any future query strings like zoneid that I don't want redirecting?




 1:10 am on Mar 31, 2013 (gmt 0)

C'mon, you know the drill. It isn't enough to say "It doesn't work". You need to spell it out in excruciating detail. What did you try, and what happened?

"What did you try" = not just the htaccess, which you've shown in part. Assuming for the sake of discussion that you've got other RewriteRules, so the RewriteEngine is already on.

"What did you try" also = what are some requests that you tried?

%{QUERY_STRING} !zoneid
by itself is ambiguous because it can mean either "zoneid is missing" OR "there is no query string at all". And, worse, it applies to all requests all the time-- not just to files in .php or whatever you use for pages. You need to constrain the rule to requests for pages, AND there has to be a preceding RewriteCond checking whether the query string exists at all. A simple . will do.

All this is assuming you truly are dumping the query string, and it won't show up later as the result of a rewrite in [L] alone.


 2:51 am on Mar 31, 2013 (gmt 0)

I actually thought I was including more detail than was really necessary. If what I have tried doesn't work then does what I tried even really matter. I understand it could if I have other code that causes issues with this zoneid redirect but I would be willing to just get basic code that would work with this zoneid redirect and then test it with my other code. Good point though that I should have included that RewriteEngine is on. Also, the comment about zoneid being ambigious is helpful as well, though it would have been more helpful with an example of what the code should be instead.


 7:42 am on Mar 31, 2013 (gmt 0)

What do you request? What do you see in the URL bar after pressing enter? What error messages do you see?

Every RewriteRule needs the L flag.

I would test THE_REQUEST for \? to ensure there is a query string present, as well as testing for !zoneid.

Use a pattern more specific than (.*) to restrict the matching to only pages. (.*) matches requests for images, CSS, js, etc too.


 7:58 am on Mar 31, 2013 (gmt 0)

overlapping g1, so we may say the same things. Or, worse, may say opposite things :(
If what I have tried doesn't work then does what I tried even really matter.

Well, what really matters is: Does "doesn't work" mean "has no effect at all whatsoever, no matter what file I request" or does it mean "It does something only not what it was supposed to do"

It's definitely easier to test a redirect than a rewrite, because you can see it working. Even if it works wrong, your browser's address bar will tell you what it thought it was doing.

Oh yes and... If the query string does contain "zoneid" do you want to keep the whole thing, or only the "zoneid" piece and still dump everything else?

The query-string-testing part is easy:

RewriteCond %{QUERY_STRING} .
RewriteCond %{QUERY_STRING} !zoneid

This, by itself, will also filter out requests for non-pages, since those will never come with a query string. At least you hope they won't. But it isn't the best way to do it; it's much better to put that part in the body of the rule. Don't look at me though: I don't know what your page URLs look like, and how many of them need to be covered by the rule.

is there a way to set up the RewriteRule so that I can just add any future query strings like zoneid that I don't want redirecting

Even mod_rewrite has its limits. One thing it can't do is see into the future and foretell what parameters you might use at some later date. So the most you can do is keep adding exceptions:

RewriteCond %{QUERY_STRING} !(zoneid|otherterm)

and you can only do it this way if there is no overlap among your parameter names. Otherwise it's


on separate lines: not A and also not B. Which may actually be less work for the server, but I'm not in a position to find out.

[edited by: lucy24 at 8:07 am (utc) on Mar 31, 2013]


 8:01 am on Mar 31, 2013 (gmt 0)

I tried:

RewriteEngine On

RewriteCond %{QUERY_STRING} !^zoneid. [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1? [L,R=301]

and got a server not found error.


 8:06 am on Mar 31, 2013 (gmt 0)

If the query string starts with zoneid then I want to keep the whole query string.


 8:17 am on Mar 31, 2013 (gmt 0)


Well, now we're getting somewhere.

First, you made a mistake that wasn't in your initial post so I was hoping it wouldn't come up.

is not the same as

The first form will only work-- that is, the condition will only succeed-- if "zoneid" is at the very beginning of the whole query string. mod_rewrite has no way of breaking a query string into its constituent bits; that's why you need the (^|&) and ($|&) business.

:: hasty detour here to edit out embarrassing blunder in previous post, with further detour to swear at Forums because the "disable smileys" feature turns itself off every time you edit ::

If the query string starts with zoneid

Aack! Every time I preview or edit, you come out with something new!

Do you mean that you only want to preserve "zoneid" if it comes first-- or that there is no possibility of it coming anywhere other than first? (Are you sure? Remember: "It is impossible to make things foolproof, because..." et cetera.)

and got a server not found error.

Woo hoo, progress, progress. Your rule DID work. But it worked by sending back the literal text "http:/ /%{HTTP_HOST}" and your browser naturally went into a fit trying to figure out what you meant. You can't use that on the "target" side of a RewriteRule. Only literal text or selected captures from the Rule or the last Condition.

This is fine, because you don't want to redirect back to whatever-form-of-the-domain-name the user asked for. Every redirect everywhere includes an extra canonicalization bit: http://www.example.com in exactly the form you want, with or without www, without extraneous port numbers, either http or https. Matter of fact, your initial post did have http://www.example.com/ on the "target" side. Where'd it go?

Now let's see how many additional posts I've overlapped this time.


 5:28 am on Apr 2, 2013 (gmt 0)

Thanks for all your help!

I now have:

RewriteEngine On

RewriteCond %{QUERY_STRING} .
RewriteCond %{QUERY_STRING} !^zoneid
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1? [L,R=301]

That seems to work in most cases but I just realized that it doesn't redirect:



 7:59 am on Apr 2, 2013 (gmt 0)

Ugh, those percent signs make me nervous. Surely they're not required here? Can't your php grab the numbers and treat them as percentages where necessary?

I just realized that it doesn't redirect:

"If the requested URL contains a query, and the query does not begin with 'zoneid', then redirect." So there's got to be something somewhere else that's preventing the rule from kicking in. Does it redirect the wrong way, or does it have no effect at all? Do you see any funny business if you watch with Live Headers or equivalent?

Worst case: something elsewhere in your code is sneaking in a rewrite, putting "zoneid" at the front of the query string.

And you should still make the "pattern" part of your rule end in .php or / Unless you've been plagued with requests for non-page files that also have queries attached.


 11:17 pm on Apr 2, 2013 (gmt 0)

I found the problem. I had an old version of an htaccess file in:


I changed my code to:

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?#\ ]*)\?[^\ ]*\ HTTP/
RewriteCond $1 !^example.com\/ad_serving_folder_name/
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1? [R=301,L]

Thanks for all your help!


 1:03 am on Apr 3, 2013 (gmt 0)

RewriteCond $1 !^example.com\/ad_serving_folder_name/

This Condition will always succeed, because the path part of the request (the part returned by $1 or preferably %{REQUEST_URI}) will never begin in "example.com".

You don't need parentheses in the first Condition, since you're not capturing.

Most servers will recognize \S for "non-space". This saves you the [^\ ] locution. And, of course, three bytes ;)

Global Options:
 top home search open messages active posts  

Home / Forums Index / Code, Content, and Presentation / Apache Web Server
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved