I’m trying to code a custom rewrite rule for ‘.htaccess’ file in my Apache webserver.
The main idea is to handle requests in the form:
example.com/foo
to ‘index.php’ file in the www_root:
example.com/index.php?queryString1=foo
As everyone knows, this is easy to do. Just by adding below lines to ‘.htaccess’ file:
RewriteEngine on RewriteCond %{REQUEST_URI} !-f RewriteCond %{REQUEST_URI} !-d RewriteCond %{REQUEST_URI} !-l RewriteRule ^(.*)$ index.php?queryString1=$1 [QSA,L]
But the problem is that when we want to add another query string to the request, for example as follows:
example.com/foo?queryString2=bar&queryString3=baz
contrary to my expectations, the following URL does the same:
example.com/foo&queryString2=bar&queryString3=baz
I don’t want the second case (in which second query string starts with ‘&’) to be executed. Also, if you write in ‘index.php’ file:
<?php echo '<pre>'.print_r($_SERVER['QUERY_STRING'], TRUE).'</pre>'; ?>
then, the output of both URLs (example.com/foo?queryString2=bar&queryString3=baz
and example.com/foo&queryString2=bar&queryString3=baz
) will be unique:
queryString1=foo&queryString2=bar&queryString3=baz
Can anyone explain what’s wrong with my codes in ‘.htaccess’ file? Thanks.
Advertisement
Answer
After above discussion, apache2 does not handle & and ? in the same way. “?” is separator of URL from QUERY_STRING, but & is a normal character as part of URL matched by apache2 RewriteRule.
In pattern of https://www.example.com/URL?QUERY_STRING, URL is only matched by RewriteRule in .htaccess file, it’s the string after the hostname and port if given, and before the query string ref., without the leading slash /.
Be careful, in apache2 configuration files vhosts.conf or alike, read when apache2 server starts, RewriteRule mathches against /URL
string (yes with the leading slash).
The OP’s case is just a chance, not general rule. I’ve tested this for the solution by triggering a 404 Not Found
error if & is involved in URL:
RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l RewriteRule ^([^&]*)$ index.php?queryString1=$1 [QSA,L]
example.com/foo&queryString2=bar&queryString3=baz
will yield a 404 error.
%{REQUEST_FILENAME}
is better than %{REQUEST_URI}
.
The character range [^&] means any character but not &. With regex ^([^&]*)$, we select a string containing no & from beginning represented by ^, to the end reprerented by $, so & sign free.