Help understanding mod_rewrite - apache

Let's say I have the following filesystem setup on my webserver:
/www/web/foo/widget.php
...
/www/app/mvc/controllers/WidgetController.php
I need to figure out how to use mod_rewrite to map page requests (and their respective GET/POST data) for widget.php to its controller WidgetController.php.
It looks like mod_rewrite is super-powerful and thus complex. Is there a quick and easy way for someone to explain to me how to accomplish this? What files do I have to change? Can someone show me a sample rule for this "widget" example?
Thanks!

Nothing is quick and easy.
Setup
First you must make sure that you have the package installed
To use mod_rewrite, you need to load the extension. Usually, this is done by inmporting the rewrite.so module in the apache2 global configuration (/etc/apache2/apache2.conf)
Usually all mod_rewrite instruction are written in the virtual host definition. (Say: /etc/apache2/site-available/000default)
Usage
First step
To enable rewrite for one site, you have to ask for it with :
RewriteEngine On
Then you can begin to write rules. The basic you need to write rules is describe by the following diagram :
(See also : How does url rewrite works?)
To help me understand how it works, always consider it from the server side (not client side).
You receive an URL from the client. This URL has a certain format that you had defined. (E.g. http://blog.com/article/myarticle-about-a-certain-topic). But apache can't understand this by himself, so we need to help him. We know that the controller is page.php and can look up article by name.
Getting information
So now we forge a regex to extract information from the URL. All regex are matched against what is following your domain name (here : article/myarticle-about-a-certain-topic without the first / -- It can be written though on recent version of rewrite)
Here we need the article's name: ^article/(.*)$ will do the job of matching URL against article/<something> and capturing <something> into $1. (For characters meaning, I advise you to look a tutorial on regex. Here ^ is beginning of the string, invisible position after the .com/, and $ the end of the URL)
So now we need to informe apache that this URL means http://myblog.com/page.php?article=myarticle-about-a-certain-topic
This is achieved by using a RewriteRule
RewriteRule ^article/(.*)$ page.php?article=$1
Restricting to conditions
To go a bit on advance topics, you may want to apply this rule only if the article name is fetch by GET method. To do this, you can include a RewriteCond like
RewriteCond %{REQUEST_METHOD} GET
It goes BEFORE a RewriteRule in the file but is tested AFTER it.
Flags
If you are making lot of redirection/rewrite, you will have to understand flags
The most used are [L] and [R]. A little explanation on those :
[R] ask for redirection, it can be tuned like [R=302] where 302 is a redirection status number of the HTTP protocol. This will force the client to make a new request with the rewritten URL. Therefore he will see the rewritten URL in his address bar.
[L] forces apache to stop treating rules. Be advise that it does mean that the current incoming URL will stop being modified, but the rewritten URL WILL go again through the process of rewriting. Keep this in mind if you want to avoid loops.
Conclusion
So you end up with the following block of instructions
RewriteEngine On
RewriteCond %{REQUEST_METHOD} GET
RewriteRule ^article/(.*)$ page.php?article=$1
See also
You can find additional resources here :
A basic tester http://martinmelin.se/rewrite-rule-tester/
Cheat sheet : http://www.ranzs.com/?p=43
Query_String examples : http://statichtml.com/2010/mod-rewrite-baseon-on-query-string.html
Tips : http://www.noupe.com/php/10-mod_rewrite-rules-you-should-know.html and http://www.ranzs.com/?p=35

Related

Rewrite dynamic url htaccess apache

I would need to perform a redirect by extrapolating a part of the url and then creating the new one.
Specifically, I have to redirect:
https://(part to be extracted).montecoasp.it
up:
https://(extracted part).montecosrl.it
PLEASE NOTE: The part to be extracted may not even be there.
Can anyone tell me what to write in the htaccess file? Should you use RewriteUrl, RedirectMatch or what? Thank you.
I assume this is what you are looking for:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(\w+\.)?montecoasp\.it$
RewriteRule ^ https://%1montecoasp.it%{REQUEST_URI} [R=301,END]
You can implement such rule in a distributed configuration file, but you should prefer to use the static http server's host configuration.
Obviously the rewriting module needs to be loaded into the http server for this. And if you want to use a distributed configuration file (".htaccess"), then you need to enable those too...
In general it is a good idea to start out with a R=302 temporary redirection and only to change that to a R=301 permanent redirection once everything is sorted out. That prevents nasty caching issues...
You definitely should start reading the documentation of the tools you are using. You want to learn how things work, you do not just want to blindly copy things. As typical for OpenSource software the apache documentation is of excellent quality and comes with great examples:
https://httpd.apache.org/docs/current/howto/htaccess.html
https://httpd.apache.org/docs/current/mod/mod_rewrite.html

Apache Rewrite Rule gives 404 Paypal IPN Redirection

I have been trying to get a rewrite rule working to redirect my old paypal IPN URL to my new one, I have tried the following in the .htaccess file and cant seem to get it to work, any help would be greatly appreciated!!
# BEGIN PayPal Fix
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^/wc-api/WC_Gateway_Paypal/
^/hosting/modules/gateways/callback/paypal.php [R=307,L]
</IfModule>
END PayPal Fix
Another thread on stackoverflow about a similar issue: Change the IPN url on existing subscription
See jon G's post about his rewrite, that is exactly what im trying to accomplish!
Thank you for any and all guidance!
There seem to be some problems with your rewrite rule.
The minor problem is that it is unusual to write such a rule in two lines. In fact, I am not sure if this is allowed in the form you use; I would expect that there would have to be at least a line continuation character. So I would put the rule into a single line first.
But the main problem is in the target of your rewrite rule. While the first part of a rewrite rule is a search pattern (regular expression), the second part (target) isn't, so you should leave away the leading ^.
Your rule then should look like this:
RewriteRule ^/wc-api/WC_Gateway_Paypal/ /hosting/modules/gateways/callback/paypal.php [R=307,L]
But I am wondering why there is no script name in your search pattern. Do you really want to map a directory to a script? Or does WC_Gateway_Paypal just appear as directory, but in fact already is mapped to a script by a rewrite rule which is evaluated before?

rewrite rule to forward old search to new search

I've search for a few hours now but I can't figure out a solution.
I just put up a new website that has a different search url than the old site. I'm trying to capture the search queries pointed at the old site and send them to the new sites search.
such as:
advanced_search_result.php?search_in_description=1&keywords=alternator
redirecting to the new sites search like:
index.php?route=product/search&search=alternator
I've tried variations of the following without any luck.
RewriteRule ^advanced_search_result\.php?.*keywords=(.*)$ index.php?route=product/search&search=$1 [R=301,L]
any help would be appreciated.
Your issue is that you are trying to map a pattern including the query string which is not possible with a RewriteRule. That is clearly documented. You need to use a RewriteCond for that:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^(?:[^&]*&)*keywords=([^\&]*)
RewriteRule ^/?advanced_search_result\.php$ /index.php?route=product/search&search=%1 [R=301,L]
Reason is that in a RewriteRule the pattern is only matched against the path component of the request URL. The query string is not part of that. Matching against the query string is only possible in a RewriteCond using the %{QUERY_STRING} variable, since such a condition can test an arbitrary string against some pattern, not only the path component of the URL. Tokens captured inside such a condition can then be cited by a %1 in a following RewriteRule, as opposed to the $1 which refers to a capture for that rule itself.
The details are explained in the official documentation of the rewriting module which is something you should always consult when working on rewriting or redirection rules. It is very well written and comes with good examples.
And a general hint: you should always prefer to place such rules inside the http servers (virtual) host configuration instead of using dynamic configuration files (.htaccess style files). Those files are notoriously error prone, hard to debug and they really slow down the server. They are only supported as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).

Rewrite query string into part of the URL file name?

I have a php site and the URLs are displayed as follow:
http://www.example.com/cheap-call-single.php?country=ALBANIA
I want to re-write it, to display as:
http://www.example.com/cheap-international-calls-ALBANIA.php
I have searched many only generators and they all say to use:
RewriteEngine On
RewriteRule ^cheap-international-calls-([^/]*)\.php$ /cheap-call-single.php?country=$1 [L]
But this is not working for me, please note that the server has the correct Apache setting enabled.
Can someone please help me with the correct syntax?
The rewriteRule you show does the inverse, it takes incoming url in the long form and translate it to the query string version (with ?).
Now the problem is what do you mean when you say: "I want to re-write it, to display as:"
The display and the rewrite are usually different things:
If the 'display' is the url seen by the user in his browser you have :
to push this way of writing urls in your application, so that the received HTML contains the right display, this has nothing to do with mod_rewrite
you may optionally perform HTTP redirections with mod_rewrite, so when you detect the old syntax (cheap-call-single.php?country=ALBANIA) you redirect the user on the right one, then the request is re-executed by the browser (and then you should have a cheap-international-calls-ALBANIA.php file on your server, else it's a final 404)
If you do not have this file on the server (so, what you have is cheap-call-single.php) then the exposed rewriteRule is right and back to step one, it's your application which should show the right url on the HTML side.
Now if your really have cheap-international-calls-ALBANIA.php and you want your application to rewrite incoming request using cheap-call-single.php to this file, based on query string parameters, you'll have some problems. Writing rules on the query string part of the request is always complex, query string arguments may appear in any order, may be written with urlencoding or not, etc. By default rewriteRules are not using the query string part.
This is something like:
RewriteCond %{REQUEST_FILENAME} cheap-call-single\.php [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)country(=|%3D)([^&]+) [NC]
RewriteRule .* /cheap-international-calls-%3.php [L,R]
Untested (not sure for the \.), and yet not managing the fact each letter in the country word would be urlencoded, and not managing the upcase of the country name. You would need a RewriteMap to transform it uppercase. But already have my headache, is this what you really need?

simple mod_rewrite q...is the solution simple too?

I've looked at many examples here and all over the internet, but I can't seem to find an answer I understand, or that accurately solves my problem. I'm looking to implement a mod_rewrite directive in an .htaccess file that renames a folder to another name but does not show the name in the url bar.
For example (the user clicks a link that directs them to):
theSite.com/folder1/folder2/folder3/
I want them to see (same as above)
theSite.com/folder1/folder2/folder3/
But I want the browser to silently function in this directory
theSite.com/folder1/some_other_folder/folder3/
I am a PHP developer, writing my first web application. I can configure apache, PHP, mysql and use them like a pro. I'm sorry, but I don't understand the syntax for mod_rewrite. I can't seem to grasp it despite looking at many tutorials as I would need to ask questions before I could move onto the next concept. Thank you for your patience.
Your case is pretty run-of-the-mill. You just need to match the static string, plus a (.*) to match everything that follows it and store it into $1, then substitue some_other_folder.
The [L] flag (and absence of the [R] flag) instructs Apache to rewrite internally without redirecting the browser, and to stop here without matching further rules.
RewriteEngine On
RewriteRule ^folder1/folder2/folder3(.*)$ folder1/some_other_folder/folder3$1 [L]
If folder3 itself is part of the "dynamic" portion, that is, anything after folder2 should be silently rewritten into some_other_folder, leave folder3 out of the rule and just capture everything that follows folder2 into $1.
RewriteEngine On
RewriteRule ^folder1/folder2/(.*)$ folder1/some_other_folder/$1 [L]
I would use following
RewriteRule /folder1/folder2/folder3/ /folder1/some_other_folder/folder3/ [L]