Add parameter using htaccess on condition - apache

This will be a simple for those familiar with Apache rules.
Situation
Using Alipay for a payment platform, the return URL cannot feature any of your own URL parameters (be it GET or POST). However, I am using Joomla and specifically Akeeba subscriptions. This component expects a parameter in the URL in accordance with the payment platform in question.
I want to detect (through one of Alipay's URL parameters) when a return page is hit and add the extra parameter.
Example (domain and page redacted)
http://...?
currency=HKD&
total_fee=2.00&
out_trade_no=211&
trade_no=2014040100276615&
trade_status=TRADE_FINISHED
Desired outcome
http://...?
currency=HKD&
total_fee=2.00&
out_trade_no=211&
trade_no=2014040100276615&
trade_status=TRADE_FINISHED&
paymentmethod=alipay
The simple addition of a &paymentmethod=alipay
Problem
I can't seem to get Apache to pick up the rule; here are a couple of attempts so far. Please note, I definitely can use .htaccess and don't need to change RewriteBase.
-- Attempt 1 --
RewriteCond %{QUERY_STRING} out_trade_no=
RewriteRule ^out_trade_no paymentmethod=alipay&out_trade_no [R,L,QSA]
-- Attempt 2 --
RewriteCond %{QUERY_STRING} (^|&)out_trade_no=(&|$) [NC]
RewriteRule ^ %{REQUEST_URI}&paymentmethod=alipay [L,R=301,QSA]
Progress
Combining the two, I have made progress but, now seem to have the Rewrite part spamming "paymentmethod=alipay" which seems to cause an error.
RewriteCond %{QUERY_STRING} out_trade_no=
RewriteCond %{QUERY_STRING} !paymentmethod=
RewriteRule ^ %{REQUEST_URI}&paymentmethod=alipay [R,L]
Now getting a redirect chain until it automatically stops at a redirect limit

If you are just trying to match a query string from that URL with that rewritecond you need to match the first one(currency). Which is the easiest.
Try this. It will send all the parameters you want.
RewriteCond %{QUERY_STRING} ^\bcurrency=
RewriteRule ^(.*)$ /$1?paymentmethod=alipay [R,QSA,L]

Related

.htaccess RewriteRule from long url to show short url

Im trying to rewrite url from long to short but cant wrap my head around this.
My survey rewrite works wonderfully but after completing my survet php redirects to www.example.com/survey_thank_you.php?survey_id=1
but I would like to show url like www.example.com/thank_you
Im not even sure if this is possible.
Im new with .htaccess and i have tried almost everthing
.htaccess
Options +FollowSymLinks
Options -MultiViews
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^survey_thank_you.php?survey_name=([0-9a-zA-Z]+)/?$ Thank_you [L,NC,QSA]
RewriteRule ^([0-9a-zA-Z]+)/?$ survey_form.php?survey_name=$1 [L,NC,QSA] #works like charm.
Any help or directions will be highly appreciated.
Solution:
Options +FollowSymLinks
Options -MultiViews
RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_id=([0-9a-zA-Z]+)/?$
RewriteRule ^survey_thank_you\.php$ /%1/thank_you [R,L,QSD]
RewriteRule ^([0-9a-zA-Z]+)/thank_you$ survey_thank_you.php?survey_id=$1 [L,NC,QSA]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([0-9a-zA-Z]+)/?$ survey_form.php?survey_name=$1 [L,NC,QSA]
but after completing my survet php redirects to www.example.com/survey_thank_you.php?survey_id=1
You need to "correct" the URL that PHP is redirecting you to after the survey. If the desired URL is /thank_you (or /Thank_you?) then PHP should be redirecting to that URL.
You then use mod_rewrite in .htaccess to internally rewrite /thank_you back into the URL that your application understands. ie. /survey_thank_you.php?survey_id=1. However, therein lies another problem, where does the 1 (survey_id) come from in the query string? Presumably you don't want to hardcode this? So this would need to passed in the requested URL. eg. /1/thank_you or perhaps /thank_you/1?
However, is this really necessary? The resulting "thank you" page is not a page that should be indexed or a page that is normally navigated to by the user, so implementing a user-friendly URL here doesn't seem to be a worthwhile exercise?
RewriteRule ^survey_thank_you.php?survey_name=([0-9a-zA-Z]+)/?$ Thank_you [L,NC,QSA]
RewriteRule ^([0-9a-zA-Z]+)/?$ survey_form.php?survey_name=$1 [L,NC,QSA] #works like charm.
You are using a survey_name URL parameter (referencing an alphanumeric value) in your directives, but a survey_id ("numeric"?) URL parameter in your earlier example? So, which is it? Or are these rules unrelated?
You state that the second rule "works like charm", but how? What URL are you requesting? That would seem to rewrite /Thank_you to survey_form.php?survey_name=Thank_you - but that does not look correct?
As mentioned in comments, the RewriteRule pattern matches against the URL-path only. To match against the query string you need an additional condition that matches against the QUERY_STRING server variable. This would also need to be an external 3xx redirect, not an internal rewrite (in order to change the URL that the user sees). Therein lies another problem... if you don't change the URL that your PHP script is redirecting to then users will experience two redirects after submitting the form.
You also need to be careful to avoid a redirect loop, since you are internally rewriting the request in the opposite direction. You need to prevent the redirect being triggered after the request is rewritten. ie. Only redirect direct requests from the user should be redirected.
So, to answer your specific question, it should be rewritten something like this instead:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_name=[0-9a-zA-Z]+/?$
RewriteRule ^survey_thank_you\.php$ /Thank_you [QSD,R,L]
The check against the REDIRECT_STATUS environment variable ensures that only direct requests are processed, not internally rewritten requests by the later rewrite. REDIRECT_STATUS is empty on the initial request and set to the string 200 (as in 200 OK status) after the first successful rewrite.
The QSD flag (Apache 2.4) is necessary to discard the original query string from the redirect response.
So the above would redirect /survey_thank_you.php?survey_name=<something> to /Thank_you.
But this is losing the "survey_name" (or survey_id?), so should perhaps be more like the following, in order to preserve the "survey_name":
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_name=([0-9a-zA-Z]+)/?$
RewriteRule ^survey_thank_you\.php$ /%1/Thank_you [QSD,R,L]
Where %1 is a backreference to the value of the survey_name URL parameter captured in the preceding CondPattern.
However, you would then need to modify your rewrite that turns this back into an understandable URL.
(But you should probably not be doing this in the first place without first changing the actual URLs in the application.)

.htaccess - Internal friendly URL rewrite for one parameter only

I am having trouble using .htaccess to internally rewrite (that is, use the requested URL to form an internal request to then provide that to the client, who still only sees the original requested URL) a URL where only one parameter is prettified, and the rest of the request parameters are still appended. Other posts on stack either concern just one relevant parameter, or wish to redirect every parameter.
That is,
https://new.mysite.com/overhoringen/open/7 should internally request https://new.mysite.com/overhoringen/open?testId=7
https://new.mysite.com/overhoringen/open/9?other=param&more=param should internally request
https://new.mysite.com/overhoringen/open?testId=9&other=param&more=param
I can do this for the first bullet, a single parameter rewrite;
RewriteEngine on
RewriteBase /
#Prettify test
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?overhoringen/open/([^/]+)/?$ /overhoringen/open.php?testId=$1 [L]
However, I am unsure how to capture the request query at the end and then append it to the internal redirect (if present at all), without the ? still in front (to avoid open?testId=9?other=param&more=param), etc.
Help with this would just be really cool. :]
Change this line:
RewriteRule ^/?overhoringen/open/([^/]+)/?$ /overhoringen/open.php?testId=$1 [L]
to:
RewriteRule ^/?overhoringen/open/([^/]+)/?$ /overhoringen/open.php?testId=$1 [L,QSA]
Adding QSA should append the additional query string to the new url.

Is my rewrite code correct?

I am trying to write rewrite code for my customer's site. I have no way of verifying if it's correct because I don't have access to the server yet. I know that sounds strange but it's what I have to accept and work around.
I plan to put this in the root htaccess file on the server. Bottom line is this URL does not work:
http://www.regions.noaa.gov/gulf-mexico/index.php/highlights/restore-act-passed/
So when the above fires, I want it to permanently redirect to:
http://www.regions.noaa.gov/gulf-mexico/highlights/restore-act-passed/
Here is what I have
RewriteEngine on
RewriteCond %{HTTP_HOST} ^regions\.noaa\.gov$ [OR]
RewriteCond %{HTTP_HOST} ^www\.regions\.noaa\.gov$
RewriteRule ^gulf\-mexico\/index\.php\/highlights\/restore\-act\-passed\/$ "http\:\/\/www\.regions\.noaa\.gov\/gulf\-mexico\/highlights\/restore\-act\-passed\/" [R=301,L]
I'd appreciate any feedback on this. Thanks.
UPDATE - thanks to all who replied. Here's what I don't understand. I found this code on my web hosting company's code generator. It seems to work:
RewriteCond %{HTTP_HOST} ^designerandpublisher.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.designerandpublisher.com$
RewriteRule ^services.html$ "http\://www.regions.noaa.gov/gulf-mexico/highlights/restore-act-passed/" [R=301,L]
I usually do like this and works fine.
IF user enter in the URL with highlights/restore-act-passed/ THEN will display contents from index.php/highlights/restore-act-passed/ in the browser.
# [NC] Means “No Case”, so it doesn’t matter whether the domain name was written in upper case, lower case or a mixture of the two.
RewriteEngine on
RewriteRule ^highlights/restore-act-passed/?$ index.php/highlights/restore-act-passed/ [NC]
IF the user enter in the URL with index.php/highlights/restore-act-passed/ THEN will display contents from _http://%{HTTP_HOST}/gulf-mexico/highlights/restore-act-passed/
RewriteRule ^index.php/highlights/restore-act-passed/?$ _http://%{HTTP_HOST}/gulf-mexico/highlights/restore-act-passed/ [NC]
You don't need to specify the HTTP_HOST, unless you will have multiple domains coming through here (add-ons, subdomains, parked domains, etc.). If you do want to specify it, it can be simplified to one line:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?regions\.noaa\.gov$
RewriteRule ^gulf\-mexico\/index\.php\/highlights\/restore\-act\-passed\/$ "http\:\/\/www\.regions\.noaa\.gov\/gulf\-mexico\/highlights\/restore\-act\-passed\/" [R=301,L]
Actually, a subdomain doesn't even need the www, but it doesn't hurt. Then, in the rewrite rule, you only need to escape specific metacharacters in the pattern, and none in the replacement string:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?regions\.noaa\.gov$
RewriteRule ^gulf-mexico/index\.php/highlights/restore-act-passed(/)?$ http://www.regions.noaa.gov/gulf-mexico/highlights/restore-act-passed/ [R=301,L]
I also made the last (trailing) / optional. Since you're going to the same domain, there is no need to repeat it:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?regions\.noaa\.gov$
RewriteRule ^gulf-mexico/index\.php/highlights/restore-act-passed(/)?$ /gulf-mexico/highlights/restore-act-passed/ [R=301,L]
The 301 code says to alert search engines that this URL or URI has permanently moved (it will show up changed in a browser address bar, too, so human visitors can choose to rebookmark it).
As this appears to be an SEO URI, presumably it will be translated into a dynamic format (/gulf-mexico/index.php?area=highlights&item=restore-act-passed). That means that the above rewrite has to be done before any SEO-to-dynamic translation. An alternative would be to directly translate it to dynamic format right here, but since you're giving a 301, presumably you want the SEO format to show in a browser or search engine result.

redirecting based on referer using mod_rewrite ignoring the GET parameters

I'm trying to restrict the access to a webpage with mod_rewrite, based on the referer.
The webpage's URL is
http://www.example.com/path/to/page.php
It is located on a Debian server in /var/www/path/to/page.php
I have a rewrite map allowedReferers containing a list of URLs
allowedReferers
http://www.example.com/test/test1.php:white
http://www.example.com/test/test2.php:white
I also have the following rewrite conditions/rules
Rewrite
Cond %{HTTP_REFERER} ^(.*)$
RewriteCond ${allowedReferers:%1|black} ^black$ [NC]
RewriteRule /* http://www.someotherplace.com [R,L]
So far this works perfectly well.
http://www.example.com/test/test1.php
http://www.example.com/test/test2.php
Can access the website, while
http://www.example.com/test/test3.php
gets redirected to someotherplace.com.
My problem is that, in real life, my referers will contain GET parameters.
e.g.
http://www.example.com/test/test1.php?id=245
My idea was to rewrite the first condition to something like this
RewriteCond %{HTTP_REFERER} ^(.*)\?.*$
or this
RewriteCond %{HTTP_REFERER} ^(.*)\?id=[0-9]*$
I've tested both regexes in Firefox' RegexTester and they behave as I want them to.
Applied to the following input
http://www.example.com/test/test1.php?id=245
they return this for $1:
http://www.example.com/test/test1.php
I expected that %1 also contains the URL minus the GET parameters.
So that, leaving the rest of the rule unchanged:
RewriteCond ${allowedReferers:%1|black} ^black$ [NC]
RewriteRule /* http://www.someotherplace.com [R,L]
should result in the expected behavior:
http://www.example.com/test/test1.php?id=234
http://www.example.com/test/test2.php?id=222
can access the website, while
http://www.example.com/test/test3.php?id=256
(or http://www.athirdplace.com/ etc.)
will be redirected to someotherplace.com
Unfortunately it does not behave as expected at all.
Having applied the change to the first condition suddenly every referer has access to the website.
As I wanted to see what actually is inside of %1, I came up with the following idea:
RewriteCond %{HTTP_REFERER} ^(.*)\?id=[0-9]*$
RewriteCond ${allowedReferers:%1|black} ^black$ [NC]
RewriteRule /* %1 [R,L]
Assuming that refering to the page from
http://www.example.com/test/test2.php?id=234
would redirect me to
http://www.example.com/test/test2.php
Wrong assumption. It redirects me to
http://www.example.com/var/www/path/to/
which is, as I mentioned in the beginning, the address of the page whose access is to be restricted.
And of course provokes a 404, as /var/www/ is docroot.
Redirecting to %1 was just a desperate attempt to debug my problem, so I do not need a solution to achieve this. What I'm looking for is a way to solve my original redirection problem.
Referers like these
http://www.example.com/test/test1.php?id=234
http://www.example.com/test/test2.php?id=222
(no matter which id is passed)
go to
http://www.example.com/path/to/page.php
while everything else goes to
http://www.someotherplace.com
Finally I would also appreciate any ideas how to debug mod_rewrite, especially ways to peek into stuff like %{HTTP_REFERER}, %1, $1, and the likes.
Just found a solution how to (at least partially) debug mod_rewrite:
http://www.latenightpc.com/blog/archives/2007/09/05/a-couple-ways-to-debug-mod_rewrite
provides a very handy trick to output some of the values mod_rewrite is using.
I modified the example a little bit, to the following:
RewriteCond %{HTTP_REFERER} ^(.*)\?id=[0-9]*$
RewriteRule (.*) /path/to/mod_rewrite_debugger.php?referer=%{HTTP_REFERER}&p1=%1 [R=301,L,QSA]
mod_rewrite_debugger.php just contains
echo "<pre>"; print_r($_GET); echo "</pre>"
The output is:
[referer] => http://vfh143.beuth-hochschule.de/tests/moodle3.php?id=3
[p1] => http://vfh143.beuth-hochschule.de/tests/moodle3.php
Which shows that my original assumption was right.
Unfortunately the debugger doesn't work anymore when the second condition is applied:
RewriteCond %{HTTP_REFERER} ^(.*)\?id=[0-9]*$
RewriteCond ${allowedReferers:%1|black} ^black$ [NC]
RewriteRule (.*) /path/to/mod_rewrite_debugger.php?referer=%{HTTP_REFERER}&p1=%1 [R=301,L,QSA]
produces the following output:
[referer] => http://vfh143.beuth-hochschule.de/tests/moodle3.php?id=3
[p1] =>
Turns out that the rules suddenly worked as originally intended. The Problem solved itself.
Maybe this helps someone.

mod_rewrite and rewritecond

I am attempting to run a rewrite based on a condition in the URI. In summary, if the uri has a string, and does not contain another string, execute the redirect. I have an error now, but need some help getting this to work.
RewriteCond %{REQUEST_URI} (.*)usb-3-hard-drive(.*) [NC]
RewriteCond %{REQUEST_URI} !(*)start$
RewriteRule .* /en/manuals/usb-3-hard-drive/start [L]
Request URL: http://www.domain.tld/dir1/usb-3-hard-drive/*
New URL: http://www.domain.tld/dir1/usb-3-hard-drive/start
Of course, if the conditions do not match, subsequent rewrites should still be honored.
thank you...
What kind of error? You should look into Apache's error log for detailed error message.
In any case -- I suspect that Apache complains on bad regex syntax. If it is not a typo on copy-paste (somehow), then the error is here: !(*)start$ -- there is no such thing as * on it's own -- you missed the dot . before it -- most likely you meant !(.*)start$.
Here is more optimized and fully working rule:
RewriteCond %{REQUEST_URI} /usb-3-hard-drive/ [NC]
RewriteCond %{REQUEST_URI} !/start$
RewriteRule .* /en/manuals/usb-3-hard-drive/start [L]
BTW -- it does not "execute redirect" as you have mentioned -- it only does silent rewrite (internal redirect) when URL will remain unchanged in browser. If you want to have proper redirect (3xx code) when URL changes in browser's address bar, then add ,R=301 (or whatever redirect code you prefer) next to the [L], i.e. [L,R=301].