Apache RewriteRule and query string

January 29th, 2009 at 8:05 am • permalink10 comments

At first look, the way Apache mod_rewrite module deals with query strings can be a little confusing. From the RewriteRule documentation:

qsappend|QSA’ (query string append)
This flag forces the rewrite engine to append a query string part of the substitution string to the existing string, instead of replacing it. Use this when you want to add more data to the query string via a rewrite rule.

Let’s try to redirect a page depending on its query string. Our rewrite rule should looks like this:

RewriteCond %{QUERY_STRING} ^id=([0-9]*)$
RewriteRule ^page\.php$ http://mydomain.site/page/%1.php [R=302,L]

According to the official documentation, you would expect the following behavior:

/page.php?id=37 -> http://mydomain.site/page/37.php
/page.php?id=40 -> http://mydomain.site/page/40.php
# and so on

However, if you don’t append something new, then the original query is passed through the rules unchanged by default.

/page.php?id=37 -> http://mydomain.site/page/37.php?id=37
/page.php?id=40 -> http://mydomain.site/page/40.php?id=40
# and so on

If you want to discard the original query string you must append an empty question mark at the end of the rule. Let’s call it the query string not append or query string discard flag.

RewriteCond %{QUERY_STRING} ^id=([0-9]*)$
RewriteRule ^page\.php$ http://mydomain.site/page/%1.php? [R=302,L]

Here’s a quick reference for dealing with query string in a RewriteRule.

Keep original query (default behavior)
RewriteRule ^page\.php$ /target.php [L]
# from http://example.com/page.php?foo=bar
# to   http://example.com/target.php?foo=bar

Discard original query
RewriteRule ^page\.php$ /target.php? [L]
# from http://example.com/page.php?foo=bar
# to   http://example.com/target.php

Replace original query
RewriteRule ^page\.php$ /target.php?bar=baz [L]
# from http://example.com/page.php?foo=bar
# to   http://example.com/target.php?bar=baz

Append new query to original query
RewriteRule ^page\.php$ /target.php?bar=baz [QSA,L]
# from http://example.com/page.php?foo=bar
# to   http://example.com/target.php?foo=bar&bar=baz

Any problem with your Apache configuration?

Visit Search Marketing Arena and ask your question.

  1. Apache .htaccess query string redirects
  2. Logging external referers with Apache
  3. Generic Apache configuration snippets

Filed in Server / Apache • Tags: , , ,


Comments

MRK says:

Thanks, this post really helped me out.

Barb says:

Thank god for you, I’ve been stuck on this for too long now…

I think there are typos in your otherwise excellent examples?
I think it should be like this (or maybe I’m clueless!):

Keep original query (default behavior)
RewriteRule ^page\.php$ /target.php [L] # NO ? on the end
# from http://example.com/page.php?foo=bar
# to http://example.com/target.php?foo=bar

Discard original query
RewriteRule ^page\.php$ /target.php? [L] # ? on the end
# from http://example.com/page.php?foo=bar
# to http://example.com/target.php # removes the q/s

Simone says:

Hi Mark,
you’re right. Fixed.

Thanks!

Maj says:

Whew, thanks! About 20 minutes of googling and trying stuff that wasn’t working!

Thanks for sharing!
maj

Henry says:

Hi all,

First, download EzyPal Paypal Shopping Cart script below is you havn’t:

http://rapidshare.com/files/279640968/ezypal157.zip (for study only plz)

After turn on Search Engine Friendly ULRs function (SEF) under Admin CP, EzyPal will rewrite all catalog and account URLs to something likes /_catalog and /_account, and it add underscores between catalog and product names.

This is the rewrite rules:

# SEF URLs
RewriteRule ^_catalog/(.*)/_(.*)(/)?$			index.php?do=catalog&c=$1&i=$2 [NC,L,QSA]
RewriteRule ^_catalog/(.*)(/)?$					index.php?do=catalog&c=$1 [NC,L,QSA]
RewriteRule ^_(.*)/(.*)(/)?$					index.php?do=$1&m=$2 [NC,L,QSA]
RewriteRule ^_(.*)$								index.php?do=$1 [NC,L,QSA]

How to remove underscores from “/_catalog” and “/_account”, and replace others with hyphen?

Thanks.

Henry says:

DONE, a rewrite rules modified version here:

http://rapidshare.com/files/281477176/ezypal157.rar (for study only)

still not perfect, can not get rid of “catalog/” from url like http://localhost/catalog/cataname/prodname.htm

http://localhost/cataname/prodname.htm will be better, who can do this…

Harry says:

Hi
I am writting the below code in httpd-vhosts.conf. but it is not working for me… Can anyone explain me where I am wrong.

RewriteCond %{LA-U:REMOTE_USER} (.+)
RewriteRule ^http://%{HTTP_HOST}:8080/seaside/UserLoginPage?userid=%1$ http://%{HTTP_HOST}:8080/seaside/UserLoginPage?[L]

Thanks

You should not have to use LA-U in this case, because mod_auth runs before mod_rewrite (on a normally-configured server). If the user is authenticated, then REMOTE_USER will be provided by the client browser on every request.

Also, the first parameter of the RewriteRule can’t be an absolute URL. It must be relative from the current host.

Please let me know if is there any other issue.

jussay says:

Hi

My client wants to redirect query string based redirection on his zen cart, I tried a lot from my side to resolve but fails, please any help from this blog? I will provide original htaccess file and path on email(not here as public area).

Please help me,\,thanks in advancee

Add a Comment




Follow Me
    Random Quote