ColdFusion / Mod_Rewrite / Taffy: Friendly URL with Query String - apache

I am somewhat of an apache newb -- let's get that out of the way first thing! I'm trying to set up "taffy", a REST API framework, on my railo instance, and I cannot for the life of me get this rewrite to work. I got it set up just fine with Coldfusion / IIS 7, but I can't replicate the results in apache.
Basically, the framework relies on getting requests like so:
/api/index.cfm?endpoint=/resource
That's fine, but it's obviously not RESTful. They say in the "taffy" docs that without any extra rules you should be able to simply call "/api/index.cfm/resource" but I've never had that work. Anyway, I want you to be able to type "/api/resource" into the URL bar and have it just work without changing the URL back to ugly "/api/index.cfm?endpoint=/resource".
Here are my rewrite rules:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule api/(.*)$ /api/index.cfm?endpoint=/$1 [QSA,L]
Looking at the logs, this is getting the URL correctly rewriting it to "/api/index.cfm?endpoint=/resource". Then, it breaks off the "?endpoint=/resource", decides it doesn't like it, and redirects simply to "/api/index.cfm"... which does nothing.
Now, as I understand it, apache is taking the query string and hiding it in the cgi QUERY_STRING variable. Railo needs to get the "endpoint" variable out of URL scope, not CGI scope.
Is there any way I can accomplish what I'm trying to do here? Incidentally, if I add R or R=301 tags as I've seen suggested, I just get put in an infinite redirect loop, which I also can't explain. At this point I'd almost be happy with a plain old redirect, but I can't get out the loop. What am I doing!!?

Related

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]

Help understanding mod_rewrite

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

Creating rewrite rules for multiple urls in the same folder

I have been asked by our client to convert a site we created into SEO friendly url format. I've managed to crack a small way into this, but have hit a problem with having the same urls in the same folder.
I am trying to rewrite the following urls,
/review/index.php?cid=intercasino
/review/submit.php?cid=intercasino
/review/index.php?cid=intercasino&page=2#reviews
I would like to get them to,
/review/intercasino
/submit-review/intercasino
/review/intercasino/2#reviews
I've almost got it working using the following rule,
RewriteRule (submit-review)/(.*)$ review/submit.php?cid=$2 [L]
RewriteRule (^review)/(.*) review/index.php?cid=$2
The problem, you may already see, is that /submit-review rewrites to /review, which in turn gets rewritten to index.php, thus my review submission page is lost in place of my index page. I figured that putting [L] would prevent the second rule being called, but it seems that it rewrites both urls in two seperate passes. I've also tried [QSE], and [S=1]
I would rather not have to move my files into different folders to get the rewriting to work, as that just seems too much like bad practise. If anyone could give me some pointers on how to differentiate between these similar urls that would be great!
Thanks
(Ref: http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html)
What I would do, is make /submit-review/ post directly to itself (or a php file) then once submitted redirect from within the PHP file.
It can be hard to force htaccess to maintain post values whilst redirecting etc
My friend found a solution to this one.
RewriteRule review/submit.php - [L]
Will catch the first rewrite and then prevent the next one, worked a treat!