views:

788

answers:

3

I'm using mod_rewrite to rewrite pretty URLs to a form supported by a Spring 2.5 application.

e.g. /category/cat1?q=x   =>  /controller?category=cat1&q=x

However from my controller I want to know the original URL the request came from (so I can generate a link if required). This approach is needed generically across all pages so it is difficult to hard code.

How can I access the original path + query string from my controller?

I have tried using $0 to include the full path but this doesn't include the query string. I can't just append the path and the query string as this would result in some parts of the path being added as parameters /category/cat1?category=cat1&q=x Note the addition of the unwanted &category=cat1 parameter, this causes the URL to no longer match that sent from the browser.

I'm hoping mod_rewrite will let me reference the full URL and encode it as a parameter so my rule could look like:

RewriteRule /category/(.+)
            /controller?category=$1&_originalUrl=${escape:$0}?${escape:<original query string>}
            [QSA]

Using my original example the end result passed through to my controller would be:

/controller?category=cat1&_originalUrl=%2Fcategory%2Fcat1%3Fsearch%3Dx&search=x

The important part is the value of &_originalUrl which should be %2Fcategory%2Fcat1%3Fsearch%3Dx which in its unescaped version is /category/cat1?q=x (the original request URL that was sent from the browser).

Any suggestions welcome, thanks in advance!

A: 

Is there a host header you can use? Sorry for being so vague, but last time I had to do this was using PHP (urgh, dont ask), and I think thats how we did it - eg REQUEST_URI (http://www.askapache.com/htaccess/mod%5Frewrite-variables-cheatsheet.html)

You also may be able to SET a host header in the rewrite (http://httpd.apache.org/docs/2.0/mod/mod%5Frewrite.html)

eg:

ReWriteRule /category/(cat1)?q=(x) /controller?category=$1&q=$2 [E=FOO:....]

(and no, I'm so totally NOT a mod-rewrite ninja)

Nic Wise
Thanks for the reply, I was a bit vague in my original question. I'm not concerned with the hostname, just the original path and query string. I've updated the question accordingly.
Richard Paul
+1  A: 

You have to capture the query string in an initial, separate step.

RewriteCond %{query_string} ^q=([^&]+)
RewriteRule ^/category/(cat1)$ /controller?category=$1&q=%1

etc.

Jonathan Feinberg
Thanks but I need to capture the entire query string, and it needs to be in a generic fashion (I don't know what parameters will be passed through). I've updated the example to use QSA as per Gumbo's suggestion.
Richard Paul
There's enough information in my answer to put you on the right road. Good luck.
Jonathan Feinberg
+2  A: 

The query can ony be tested with RewriteCond since RewriteRule does only test the URL path. See Jonathan Feinberg’s example how to do that.

But you could also just set the QSA flag and the old query gets automatically appended to the new one:

RewriteRule ^/category/([^/]+)$ /controller?category=$1 [QSA]


Edit    In response to your comment to this question: If you want to get the initial requested URI path and query, you need to extract it from the request line (THE_REQUEST variable):

RewriteCond %{THE_REQUEST} ^[A-Z]+\ ([^\s]+)
RewriteRule ^/category/([^/]+)$ /controller?category=$1&_originalUrl=%1 [QSA]

But in most languages there is an environment variable with the very same information.

Gumbo
Thanks for the QSA example. Sorry my example wasn't very accurate, I am using [QSA] to automatically appending the original query string to the rewritten URL. What I'm trying to achieve is the get the original (unrewritten) path + query string as the user sees them in the browser, and pass that as an encoded parameter to my controller.
Richard Paul
Gumbo