I'm trying to take a URL with multiple querystring parameters into a folder structure URL and am getting a 500 internal server error.
My incoming URL looks like
www.fivestarprofessional.com/ag?PY=16&PF=wm&MKT=Delaware
My destination URL I need written as
delaware.fivestarprofessional.com/16/wm/index.html
I created 3 RewriteCond statements to capture the parameters and a RewriteRule to create the output
RewriteCond %{QUERY_STRING} !^(PY=.*)$ [NC]
RewriteCond %{QUERY_STRING} !^(PF=.*)$ [NC]
RewriteCond %{QUERY_STRING} !^(MKT=.*)$ [NC]
RewriteRule %3.fivestarprofessional.com/%1/%2/index.html
Any assistance would be greatly appreciated.
You can use this rule for your redirection:
RewriteCond %{QUERY_STRING} (?:^|&)PY=([^&]+) [NC]
RewriteCond %1::%{QUERY_STRING} (.*?)::(?:|.*&)PF=([^&]+) [NC]
RewriteCond %1/%2::%{QUERY_STRING} (.*?)::(?:|.*&)MKT=([^&]+)
RewriteRule ^ag/?$ http://%2.fivestarprofessional.com/%1/index.html? [L,NC,NE,R=302]
% variables are captured only from the most recent condition using same %{QUERY_STRING}
Try this one:
RewriteCond "%{QUERY_STRING}" "^PY=([^&]+).*&PF=([^&]+).*&MKT=([^&]+)" [NC]
RewriteRule "www.fivestarprofessional.com/ag" "%3.fivestarprofessional.com/%1/%2/index.html"
The following issues have been corrected:
RewriteRule takes 3 arguments instead of 2.
Arguments to RewriteCond hadn't been enclosed in quotes.
The backreferences into the RewriteCond rules ...
... only refer to the last condition matched (pointed out by #anubhava, being documented in the apache httpd docs). Therefore, the rules need to be collapsed in one.
... referred to the parameter name plus the complete remainder of the query string
... would have matched against query string starting with the respective ul parameter due to the use of the ^ anchor.
... would have been empty anyway, as the rules fired when the patterns did not match ( use of ! prefix )
Recommended reading is the proper section of the apache httpd documentation.
The solution as it stands assumes that...
the query string starts with the url parameter PY
the order in which the url parameters PY, PF, MKT appear in the query string is fixed.
Related
I'm trying to complete the following rule in my .htaccess.
I have this .htaccess in root directory of domain1.com and want to arrange the following redirect domain1.com/index.php?domain2.com?page.html which will bring all visitors to domain2.com/page.html.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^
RewriteRule (.+)\.php\?(.+)\?(.+) http://$2/$3 [R=301,L]
Solved.
domain1.com/domain2.com/page.html
RewriteEngine On
RewriteCond %{HTTP_HOST} ^
RewriteRule (.+)\/(.+) http://$1/$2 [R=301,L]
Instead of constructing your initial URLs like domain1.com/index.php?domain2.com?page.html - which requires you to capture two separate backreferences (the second ? will be URL encoded). It would be better to format your URL more conventionally, like the following instead:
domain1.com.com/index.php?redirect=domain2.com/page.html
(Not sure why you were substituting a ? for the first slash in the URL being passed?)
Then you could do something like the following. Note that you need to use a condition that checks against the QUERY_STRING server variable.
RewriteCond %{QUERY_STRING} ^redirect=([^&]+)
RewriteRule ^index\.php$ http://%1 [QSD,R,L]
%1 is a backreference to the last matched CondPattern.
The QSD flag is required to discard the original query string from the request.
HOWEVER, you need to perform additional validation on the domains that can be redirected to, otherwise this will likely be abused for malicious intent once it is discovered.
UPDATE:
RewriteCond %{HTTP_HOST} ^
RewriteRule (.+)\/(.+) http://$1/$2 [R=301,L]
The RewriteCond directive here isn't doing anything. If you are wanting to validate that a Host header is present (ie. is not a HTTP/1.0 request) then you should change the regex ^ to . (simply a dot). However, if you are on a shared server then this test is probably redundant.
By using the URl-path, this will "break" if the destination hostname is the same as the source.
I have a Rewrite Rule as
RewriteRule settings/([a-zA-Z0-9_]+)/?$ settings/?path=$1 [NC,L,QSA]
It basically takes path parameter and rewrite url like this
http://localhost/settings/?path=abc => http://localhost/settings/abc
But there's a problem! when I provide something like http://localhost/settings/abc/?path=xyz the path parameter is overwritten with xyz and it opens http://localhost/settings/abc/ with data of xyz
After further digging I noticed that the problem is caused by the parameters in URL itself. By default its picking up the value of last parameter with same name http://localhost/settings/account/?path=profile&path=account&path=profile
so the value that i can get in this case for $_REQUEST['path'] is profile. How can I just pickup the first value from the same parameters and ignore the rest of them?
One thing I can do is to remove [QSA] from the RewriteRule, that will do the fix but I need other parameters passed in url as well.
How can I achieve this?
PHP recognizes brackets [] appended to a parameter, e.g.
http://localhost/settings/account/?path[]=profile&path[]=account&path[]=profile
will be translated into an array
$path = $_GET['path'];
print_r($path);
shows
Array ( [0] => profile [1] => account [2] => profile )
This way, you can access any of the "paths" you like.
I could imagine some RewriteCond surgery, in order to remove part of a query string
RewriteCond %{QUERY_STRING} ^(.*)&path=.*?&(.*)$
RewriteRule ^ %{REQUEST_URI}?%1&%2
RewriteCond %{QUERY_STRING} ^path=.*?&(.*)$
RewriteRule ^ %{REQUEST_URI}?%1
RewriteCond %{QUERY_STRING} ^(.*)&path=.*$
RewriteRule ^ %{REQUEST_URI}?%1
Depending on where the path is, this would remove it from the query string. And finally, the last rule would add the new path again
RewriteRule settings/([a-zA-Z0-9_]+)/?$ settings/?path=$1 [NC,L,QSA]
Although, I don't know, if this is working at all, and how (in)efficient this is.
There is one caveat, you must check for REDIRECT_STATUS to prevent an endless loop.
You can use these 2 rules in your .htaccess:
# remove path= parameter from query string, if it exists
RewriteCond %{THE_REQUEST} \?(.*&)?path=[^&]*(?:&(.*))?$ [NC]
RewriteRule ^settings/. %{REQUEST_URI}?%1%2 [L,R=301,NE,NC]
# your existing rule
RewriteCond %{THE_REQUEST} \?(.*&)?path=[^&]*(?:&(\S*))? [NC]
RewriteRule ^settings/ %{REQUEST_URI}?%1%2 [L,R=302,NE,NC]
RewriteCond %{QUERY_STRING} !(?:^|&)path= [NC]
RewriteRule ^(settings)/(\w*)/?$ $1/?path=$2 [NC,L,QSA]
In fact I am working on a small php script, and now I am struggling with doing redirect using mod-rewrite.
What i want is to redirect
www.xx.com/motivational/api.php?latest=1
to
www.xx.com/api.php?latest=1&app=motivational
I tried this but it doesn't work:
RewriteRule ^/motivational/api\.php$ /api.php?latest=&%{QUERY_STRING}
%{QUERY_STRING} represents the entire query string, in your case latest=1. So when you append it to ...?latest= in your substitution string the result is ...?latest=latest=1 which is not what you want.
Change your rule to
RewriteRule ^/motivational/api\.php$ /api.php?%{QUERY_STRING}&app=motivational
and you should be fine.
Or you could do:
RewriteRule ^/motivational/api\.php$ /api.php?app=motivational [QSA]
The QSA flag means to append the new query string to the old, rather than to replace it, so your latest variable will not be lost.
You can not match against query strings in a RewriteRule, You will need a RewriteCond to match query strings in url :
RewriteEngine on
RewriteCond %{THE_REQUEST} /([^/]+)/api\.php\?latest=1 [NC]
RewriteRule ^ /api.php?latest=1&app=%1 [NC,L,R]
%1 is part of the regex "([^/]+)" in RewriteCond, it contains dynmically captured path in the request line.
I would like to change any url containing the query string &preview_nonce= with any value passed to preview_nonce.
I understand that I have to rewrite based on the condition:
RewriteCond %{QUERY_STRING} ^preview_nonce=(.*)$
But I'm getting caught up only removing that from the query string and leaving everything else, including query strings.
Example URLs:
about-us/history/commitment/?preview=true&preview_id=9999&preview_nonce=9x323k1
stories/companies/?preview=true&preview_id=8888&preview_nonce=c448s88
The desired results:
about-us/history/commitment/?preview=true&preview_id=9999
stories/companies/?preview=true&preview_id=8888
You can use this rule for query string removal:
RewriteCond %{QUERY_STRING} ^(.+?&)?preview_nonce=[^&]*(?:&(.*))?$ [NC]
RewriteRule ^ %{REQUEST_URI}?%1%2 [L,NC,R=302]
Make sure this rule is placed before other WP rules.
UPDATE: This works:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{THE_REQUEST} ^[A-Z]+\ ([^\s]+)
RewriteRule (.+) /index.cfm?event=checkuri&uri=%1 [QSA]
Some background...
So we already have a catchall redirect in our .htaccess file which is this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.+) /index.cfm?event=checkuri&uri=$1
This ties into a database table that checks the URI for a match. so if we just moved a site that used to have this page:
/some-awesome-article.html
Onto our system, and the new address is
/awesome-article/12442
and someone tried to access the old URI, our system would check for this, find a match, and forward them to the new home: /awesome-article/12442
This system works awesome, with one exception. If the URI is something like /index.php?id=123412 then the whole system falls apart. In fact /index.php/whatever won't work either.
Everything else works except for this. We do not use PHP for our web application (although support says its in an admin console on the server somewhere).
So basically what I need is if index.php is detected anywhere it will forward the URI to our
existing system:
How can i modify this to fix it?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.+) /index.cfm?event=checkuri&uri=$1
Try changing your code to:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.+) /index.cfm?event=checkuri&uri=$1 [L,QSA]
QSA is for Query String Append that will make sure to append existing query parameters with the new ones.
Rewriting with mod_rewrite does not work on the full URL. In fact, the regex in the RewriteRule does only get the path and file, but not the query string. And so the backreference $1 will only contain "index.php" and nothing else.
Additionally, the RewriteRule does change the query string because there is one in the target pattern. Because the flag [QSA] (query string append) is not present, the query string of the original request gets replaced instead of appended. So the query string is gone after this rewriting.
This would be a lot easier if you wouldn't mess with the query string. The easiest way of rewriting any url that is not an existing file would be if the second line would be simply RewriteRule (.+) /index.cfm - you could then get all info about the current request, including query string, path and file, in the script.
So now you'd have to fiddle with the query string. Adding [QSA] will pass the query string to your script and you'd have to detect what's inside. This will work only if you do not expect the query string to contain parameters named "event" and "uri" - these will be overwritten by your rewriting. If you need to add the original query string to the URL, it's a bit more complicated, because the string needs to be url-encoded.
Here's how to do that.
Based on your comments, it sounds like you need to use the Query String Append QSA flag on your rule like this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.cfm?event=checkuri&uri=$1 [QSA,L]
In your example case the rewrite would look like:
/index.cfm?event=checkuri&uri=index.php&id=123412
Sven was very close so I'm giving him the check
This ended up working perfectly:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{THE_REQUEST} ^[A-Z]+\ ([^\s]+)
RewriteRule (.+) /index.cfm?event=checkuri&uri=%1 [QSA]