Ok so I have a url like this:
http://example.com/admin/test.php?action=edit&id=2
However I need to add in a rule to redirect this to another url with a query string like this:
http://example.com/admin/login.php?redirect=test.php%3Faction%3Dedit%26id%3D2
I added a rule like this:
RewriteRule ^admin/(.*)?$ /login.php?redirect=/admin/$1?%{QUERY_STRING} [R,L]
And it works for the most part but there is one problem, the query string is not being escaped so it is thinking those are other $_GET variables. It looks like this:
http://example.com/admin/login.php?redirect=test.php%3Faction=edit&id=2
So the redirect is reading as test.php?action=edit. It is missing the id=2 because it is reading it as another $_GET variable instead of part of the $_GET['redirect'].
Is it possible to escape the %{QUERY_STRING} ? I have googled everything I can think of and cannot find an answer anywhere.
Well, if you don't mind having a bunch of &'s at the end of your encoded URL, you can use optional captures and encode the & by hand. Something like:
RewriteCond %{QUERY_STRING} ^([^&]+)(?:&(.*)|)$
RewriteRule ^admin/(.*)?$ /login.php?redirect=/admin/$1\%3F%1\%26%2 [L,NE,R]
So if you go to:
http://example.com/admin/test.php?a=1&b=2
you get redirected to:
http://example.com/login.php?redirect=/admin/test.php%3Fa=1%26b=2
However, going to:
http://example.com/admin/test.php?a=1
will redirect you to:
http://example.com/login.php?redirect=/admin/test.php%3Fa=1%26
and your php script will extract the $_GET['redirect'] parameter as: /admin/test.php?a=1&. As long as you don't mind having that stray ampersand at the end.
If you have a lot of possible variables, and don't care about the ampersand, just add more (?:&(.*)|) to the end of the querystring condition and match them with backreferences (example, 4):
RewriteCond %{QUERY_STRING} ^([^&]+)(?:&(.*)|)(?:&(.*)|)(?:&(.*)|)$
RewriteRule ^admin/(.*)?$ /login.php?redirect=/admin/$1\%3F%1\%26%2\%26%3\%26%4 [L,NE,R]
Related
My .htaccess is something like this
RewriteRule ^search/([A-Za-z0-9-]+)$ search.php?keyword=$1 [L]
and it correctly displays results for example.org/search/tomato
but now i'd like to pass variables to it, but when i do it like
example.org/search/tomato?color=green
it doesn't work.
what's the common practice to solve this problem?
Use:
RewriteRule ^search/([A-Za-z0-9-]+)$ search.php?keyword=$1 [QSA,L]
QSA|qsappend When the replacement URI contains a query string, the
default behavior of RewriteRule is to discard the existing query
string, and replace it with the newly generated one. Using the [QSA]
flag causes the query strings to be combined.
I have a few different mod-rewrite rules working, but this last one refuses to pass the 3 parameters to my script (index.php)
I do get the p=value, but the id, rid and chk vars don't even get defined...
A URL might look like this . . . .
http://www.domain.com/pagename.htm?id=29&rid=174&chk=a9cdca614135bbef2fb1f2bedf171f61
The rule...
RewriteRule ^/pagename\.htm\?id\=([0-9]+)&rid\=([0-9]+)&chk\=([a-f0-9]{32})$ /index.php?p=pagename&id=$1&rid=$2&chk=$3 [L]
Output of print_r($_REQUEST);
Array ( [p] => pagename )
I simply can not understand why this does not work..
Like #MarcB said, rewrite rules don't include the query string and you have to use a RewriteCond to check it. This is what would work for you based on your example above:
RewriteCond %{QUERY_STRING} ^id=([0-9]+)&rid=([0-9]+)&chk=([a-f0-9]{32})$
RewriteRule ^pagename.htm index.php?p=pagename&id=%1&rid=%2&chk=%3 [L]
Or like I said above, you can also use the QSA flag like:
RewriteRule ^(pagename).html index.php?p=$1 [L,QSA]
And that will append any additional query string on to index.php, but doesn't validate it (which should REALLY not be done in mod_rewrite). It also allows you to add additional parameters, doesn't require a change of the rules to accommodate them and won't break if the key/values are in different order or case. Note: I added parenthesis around pagename and used the match $1 in the rewritten url. This is so it is easier to change the page name for multiple rules because you don't have to change it in two places.
I'm trying to rewrite an url from:
http://domain.com/aa/whatever/whatever.php
to
http://domain.com/whatever/whatever.php?language=aa
However, depending on existing $_GET variables, it either has to be ?language or &language.
To do this, I use 2 regexes with the [L] flag:
RewriteRule ^([a-z]{2})/(.*\.php\?.*) /$2&language=$1 [L]
RewriteRule ^([a-z]{2})/(.*) /$2?language=$1 [L]
The second one works as expected... The first one however is never hit (it falls through to the second regex, which does hit), even though Regex Coach does show me that it should.
edit:
If just read that I need to use two backslashes to escape the question mark. If I do this, it does hit on the first regex but never find the other GET variables.
From the documentation for mod_rewrite the pattern in RewriteRule matches against the part of the URL after the hostname and port, and before the query string so the query string is not included. That is why you don't get the other variables.
To add a new query string parameter language=xx whilst preserving any existing query string you need to use the QSA flag (query string append). With this flag, just one rule based on your second case should be sufficient:
RewriteRule ^([a-z]{2})/(.*) /$2?language=$1 [QSA]
You could setup the URL rewrite to pass the language to the php script via the PATH_INFO element of the $_SERVER superglobal. Just pass the language to the script like so:
foobar.php/en?args
In this case, $_SERVER[PATH_INFO] would equal /en
Consider the following scenario:
I want to be able to access http://www.example.com/word/hello/, where the word hello is variable. So I set up .htaccess to configure that.
RewriteEngine On
RewriteRule ^word/(.+)/?$ displayword.php?word=$1 [L]
I used .+ because I also want to filter any symbols such as ?+-.!;: etc.
And I set up my PHP file accordingly:
<?php
echo $_GET['word'];
?>
Remember that this is just a scenario. Now, I went to this URL: http://www.example.com/word/Are you ok?/, and the page outputted this:
Are you ok
And I couldn't figure out why. But then I realised that the question mark symbol is the starting point of the URL variables.
So is there a way to 'url encode' the question mark in the above example, in order for it to be displayed correctly?
There is no need to encode it, try this:
RewriteEngine On
RewriteRule ^word/([a-zA-Z0-9-=_.?]+)/?$ displayword.php?word=$1 [L]
It will display ? in the parameter and any other character you add to the [group]. I did not test if the rule works, though, but I suppose it does. Looks ok and that is not the question.
I don't know heaps about .htaccess files, but you could change your PHP script to use $_SERVER['PATH_INFO'] instead of $_GET or $_REQUEST.
Particularly, this comment might help you out.
In the HTTP protocol the "?" separates the querystring from the rest of the URL, so I don't think it will be possible to use it directly inside the URL. One solution would be to encode the question mark into %3F.
Then you can use string urldecode (string $str) to decode the string.
See this URL Encoding Reference for the encoding of other characters.
Change your code to this:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+word/([^/]+) [NC]
RewriteRule ^ index.php?word=%1 [L,QSA]
Reason this works is because RewriteRule works on %{REQUEST_URI} which gets URI i.e. string before question mark ? however %{THE_REQUEST} works on the full URL that includes question mark ? as well.
I'm struggling with a redirect problem. I need to redirect the following URL with mod_rewrite thorough .htaccess
http://www.mysite.com/somescript.php?&lang=php&var=1&var=2
to the following
http://www.mysite.com/somescript.php?lang=php&var=1&var=2
So, basically I just need to remove the
&
before
lang=php
However, the order is important. Sometimes
&lang=php
appears after other variables in the querystring. in this scenario I need the
&
to remain part of
&lang=php
Is this possible?
To summarise, if &lang=php appears at the beginning of the query string, remove the &. If &lang=php appears anywhere else in the query string, the & must remain.
Hope this is clear!
I would change the script myself but unfortunately I am not the developer, and he doesn't seem too helpful at the moment; this is a quick fix.
I would replace ?& with ?:
RewriteCond %{QUERY_STRING} ^\&(.*)$
RewriteRule ^somescript\.php$ /somescript.php?%1 [L,R=301]
why don't you match "?&" and replace it by "?" ?
Something like:
RewriteRule ^(.*)?&(.*) $1?$2 [L]
(not tested)
Because I think the combination "?&" is never valid...(?)