Forum Moderators: phranque

Message Too Old, No Replies

htaccess rewrite, matching the querystring

what am I doing wrong?

         

httpwebwitch

3:51 pm on Jan 27, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



So I've got this PHP script, "backend.php". But it's never seen by the public; I use rewrite rules to map public-facing URLs to it.

for instance,
/obj/123/method/
is actually
/backend.php?userid=123

and
/obj/99999/method/
is actually
/backend.php?userid=99999

This is all working fine, using this rule:

[quote]RewriteRule ^obj/([0-9]+)/method/$ /backend.php?userid=$1 [L]
[/quote]

Now, I've added a feature, whereby sometimes the app will append a querystring to the request, like so:

/obj/99999/method/?referer=[url of this page]
for example:
/obj/99999/method/?referer=%2Fobj%2F99999%2Fmethod%2F

That's where the problem begins.
I'd like that URL to call the backend script thusly:
/backend.php?userid=99999&referer=%2Fobj%2F99999%2Fmethod%2F

Here are the htaccess rules that I *thought* would do the trick. But when I run it the backend is only getting the userid variable, not the referer.

[quote]
RewriteRule ^obj/([0-9]+)/method/\?referer=(.+)$ /backend.php?userid=$1&referer=$2
RewriteRule ^obj/([0-9]+)/method/$ /backend.php?userid=$1 [L]
[/quote]

Can anyone see what's wrong with this?

jdMorgan

4:24 pm on Jan 27, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Query strings are not part of a URL, but rather, data appended to a URL to be passed to the resource *at* that URL. As a query string has no part in *locating* a resource, it is not considered to be part of the URL itself. (This may be clearer if you ignore your specific SEO-friendly rewrite application for the moment, and think in terms of purely-static HTML pages.)

Therefore, mod_rewrite's RewriteRule, which examines only the URL-path, cannot 'see' your query string.

The simplest solution is to remove the "referer=" stuff from your RewriteRules, and use the [QSA] flag, which tells the RewriteRule to append the "userid=" query string to any existing query string in the request rather than replacing it, which is the default behavior.

Also, always use the [L] flag unless you have a very good reason not to. Always use it unless the current rule's output must be processed by a subsequent rule. Otherwise, you will waste an awful lot of CPU cycles on your server. BTW, the [L] flag terminates rewriterule processing only if the current rule is invoked.


RewriteRule ^obj/([0-9]+)/method/$ /backend.php?userid=$1 [QSA,L]

Jim

httpwebwitch

5:45 pm on Jan 27, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



jdMorgan, I did not know about the QSA flag.

I changed the RewriteRule exactly as you suggested;
Now, if I request the following URL:
/obj/12345/method/?a=1&b=2&c=3

the back end receives this:
/backend.php?userid=12345&a=1&b=2&c=3

That totally solved the problem. Thanks!

Caveat: It does mean that the backend can receive requests containing arbitrary querystrings, which I'll need to validate on that layer. That's not a problem, but it is something to be aware of when using the QSA flag.