mod_rewrite add REQUEST_URI to URL-parameter, handle it with ColdFusion - apache

I have a strange problem with mod_rewrite in combination with ColdFusion:
I'm using the following rewrite rules in my virtualhost-configuration:
RewriteEngine On
RewriteRule ^$ index.cfm [L]
# Add trailing slash if missing
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(?i)^[\\/]CFFileServlet
RewriteCond %{REQUEST_URI} !index.cfm
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ $1/ [L,R=301]
# Clean up multiple slashes in URL
RewriteCond %{HTTP_HOST} !=""
RewriteCond %{THE_REQUEST} ^[A-Z]+\s//+(.*)\sHTTP/[0-9.]+$ [OR]
RewriteCond %{THE_REQUEST} ^[A-Z]+\s(.*/)/+\sHTTP/[0-9.]+$
RewriteRule .* http://%{HTTP_HOST}/%1 [R=301,L]
# Pass all non physically existing files/folders to index.cfm in URL.original_url
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/cms/
RewriteRule ^(.*)$ /index.cfm?original_url=$1 [QSA,PT,L]
Everything is working fine except for one thing:
If I call http://www.example.com/test/?asdf my URL.original_url reads like this original_url=/test/index.php&asdf and I can't figure out why there is index.php in it.
I tried already leaving out the PT-flag but it doesn't work without it. All pages e.g. http://www.example.com/test/ return 403 - Forbidden and in title of the page says "JRun Servlet Error".
Thanks for any ideas on this one!
EDIT:
Ok, I missed something important: the folder /test/ actually exists in my documentroot! Other URLs like /test/does_not_exist/ are not affected by the described problem.
Summed up:
http://www.example.com/test/ -> URL.original_url gets /test/index.php
http://www.example.com/test/does_not_exist/ -> URL.original_url gets /test/does_not_exist/ which is my expected behaviour.

Related

Rewrite URLs in .htaccess for replacing Query parameters with forward slash (id?=value)

I have made sure that rewrite engine is enabled and removing .php extensions is working so I know that isn't the issue.
what I'm trying to do is simply remove the ?id=value aspect of the URL, so basically making the URL look like such:
folder/medias/value
Instead of
folder/medias?id=value
My current .htaccess looks like this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
RewriteRule ^404/?$ /404.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^ 404.php [L,R]
With your shown samples/attempts, please try following htaccess Rules. Please make sure to clear your browser cache before testing your URLs.
RewriteEngine ON
##Rules for external rewrite.
RewriteCond %{THE_REQUEST} \s/([^.]*)\.php\?id=(\S+)\s [NC]
RewriteRule ^ /%1/%2? [R=301,L]
##Rule for internal rewrite.
RewriteRule ^([^/]*)/([^/]*)/?$ $1?id=$3 [L]
You may try this code inside the /folder/.htaccess (create this file if it doesn't exist):
RewriteEngine On
# External redirect from /folder/media?id=val to /folder/media/val
RewriteCond %{THE_REQUEST} /(\S+?)\.php\?id=([^&\s]+)\s [NC]
RewriteRule ^ /folder/%1/%2? [R=301,L,NE]
# Internal rewrite from /folder/media/val to /folder/media?id=val
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([\w-]+)/([\w-]+)/?$ $1.php?id=$2 [L,QSA]
Trailing ? in first rule is to remove query string from original URL.
%{REQUEST_FILENAME} !-f and %{REQUEST_FILENAME} !-d is to skip existing files and directories from rewrite in 2nd rule.

Joomla: Permanently redirect from example.com/index.php/foo/bar to example.com/foo/bar (no index.php in URL)

.htaccess
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
With this setup the page /foo/bar is accessible under the pretty URL example.com/foo/bar while the ugly URL example.com/index.php/foo/bar is still valid. What I need to achieve is a permanent redirection from example.com/index.php/foo/bar to example.com/foo/bar.
RewriteRule .* index.php [R=301,L] doesn't work.
RewriteRule (.*) index.php/$1 [R=301,L] does the exact opposite, it redirects from example.com/foo/bar to example.com/index.php/foo/bar. Please help me out!
I recommend writing this:
RewriteEngine On
RewriteBase /
# remove index.php from / OR any /dir
RewriteCond %{THE_REQUEST} /index\.php [NC]
RewriteCond %{REQUEST_URI} ^(.*/)index\.php$ [NC]
RewriteRule ^ %1 [L,R=301,NE]
# redirect rule to remove /index.php/ from start
RewriteRule ^index\.php(/.*) $1 [L,R=301,NC]
RewriteCond %{REQUEST_URI} !^/index\.php [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
In the new rule, we match a pattern using regex ^index\.php(/.*) which matches a URI that starts with /index.php/ followed by zero or more of any characters. (/.*) is our match and the capture group after /index.php which is used as back-reference i.e. $1 (string that we've captured in group #1) in target to get a URI after /index.php as desired.
References:
Apache mod_rewrite Introduction
.htaccess tips and tricks

htaccess point request to sub-directory if file doesn't exists and does under the subdirectory

I'm having a really hard time with trying to get this to work so I have a sub-directory example.com/projects with a directory under that called test and I'd like it if someone typed example.com/test it would show the file from example.com/projects/test but if the file does not exist I would like it to post a 404 error.
Additionally if possible I would like any time example.com/projects/test was typed it would redirect to example.com/test instead but if someone goes to just projects/ I want them to be able to stay there.
I have tried the following .htaccess files so far
This works almost perfectly passing through the files unless the file doesn't exist in which it throws a 500 Internal Server Error
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ projects/$1 [PT]
I thought something like this might work to only pass through if the file existed under projects but doesn't work at all:
RewriteCond projects/%{REQUEST_FILENAME} -f
RewriteCond projects/%{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ projects/$1 [PT]
For the second part pointing anything that goes to /projects/test to strip /projects I tried this (placed before the code above)
RedirectMatch ^/projects/(.+)$ /$1
Only to find a redirect loop. How can i prevent this?
My current .htaccess file for reference:
ErrorDocument 404 /404.html
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^example2\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.example2\.com$
RewriteRule ^/?$ "http\:\/\/example3\.org" [R=301,L]
#RedirectMatch ^/projects/(.+)$ /$1
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule ^(.*)$ projects/$1 [PT]
You can use these rules in your root .htaccess:
DirectoryIndex index.html
RewriteEngine On
RewriteCond %{THE_REQUEST} /projects/(\S+)\sH [NC]
RewriteRule ^ /%1 [L,R=302,NE]
RewriteCond %{DOCUMENT_ROOT}/projects/$1 -f [OR]
RewriteCond %{DOCUMENT_ROOT}/projects/$1 -d
RewriteRule ^(.+)$ projects/$1 [L]

how to fix htaccess error with multiple rewrite rule - ERR_TOO_MANY_REDIRECTS

why this htaccess has error. it says "to many redirect" please help thanks
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule .* index.php [L]
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
RewriteEngine on
Options +FollowSymLinks
RewriteCond %{THE_REQUEST} ^.*/index\.php
RewriteRule ^(.*)index.php$ http://us.domain.com/ae_en/$1 [R=301,L]
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^us\.domain\.com$
RewriteCond %{REQUEST_URI} !^/(ae_en|ae_ar) [NC]
RewriteRule ^(.*)/ae_en/%{REQUEST_URI} [R=301,L]
I cannot try the wrong code, it always appear error
There are several issues with your .htaccess. I would suggest both re-ordering and editing the rules.
This would be a better approach, in my opinion. I'll explain the parts below.
RewriteEngine on
RewriteBase /
Options +FollowSymLinks
# External redirect: Remove www from domain
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
# External redirect: Ensure language code is set
RewriteCond %{HTTP_HOST} ^us\.domain\.com$
RewriteCond %{REQUEST_URI} !^/(ae_en|ae_ar) [NC]
RewriteCond %{REQUEST_URI} !^/index.php$ [NC]
RewriteRule ^(.*)$ /ae_en/$1 [R=301,L]
# Internal redirect: Pass everything non-existent to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule .* index.php [L]
Structure
First, general options and settings should come at the top and only once, i.e.
RewriteEngine on
RewriteBase /
Options +FollowSymLinks
Second, I like to get the external URL to show up correctly, so I group all external redirects here - denoted with comments in the above code block.
Third, internal "redirects" follow, meaning mapping the (now correct and final) external URL to the correct scripts.
This structure ensures that the internal scripts are only matched on a URL that will not change when re-run against the .htaccess on the next RewriteRule match.
Omitting external redirect for index.php
I guess you added the index.php redirection handling after adding in the internal redirect, which probably has caused index.php to show up in the browser. So, with the above structure in place, I assume it will not show up again.
Error in last RewriteRule
As Mike Rockett pointed out in the comment above, there also was an error in the last RewriteRule.
Avoid redirect loop
To avoid a redirect loop when rewriting to index.php with the last rule, you have to explicitly exclude index.php from language code redirection, i.e.
RewriteCond %{REQUEST_URI} !^/index.php [NC]

Rewrite root access to be served from a sub-domain

Options -Indexes
RewriteEngine on
Options +FollowSymLinks
RewriteRule ^$ 2012/index.php [L]
RewriteCond %{DOCUMENT_ROOT}/2012%{REQUEST_URI} -f
RewriteRule .* 2012/$0 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* 2012/index.php$0 [QSA] #<-- this is wrong here, and gives 500 error
I am trying to server all my urls from the 2012 subfolder.
I tried the above script, and it fails for urls like:
index.php/admin/controller/action?id=123
which should be resolved from the subfolder
2012/index.php/admin/controller/action?id=123
what is wrong?
I'm going to guess that the URI /index.php/admin/controller/action?id=123 fails the -f test for %{DOCUMENT_ROOT}/2012%{REQUEST_URI}, and is instead getting rounded up by the last rule: RewriteRule .* 2012/index.php?q=$0 [QSA], turning the URI into /2012/index.php?q=index.php/admin/controller/action&id=123. You'll have to add a special case for this because the first condition/rule allows the existing files to be rewritten as-is, and the last condition/rule acts as a "catch-all" (and the very first rule is simply for the special case when the request URI is /). Try something like this:
RewriteRule ^$ 2012/index.php [L]
RewriteCond %{REQUEST_URI} ^/index\.php [OR]
RewriteCond %{DOCUMENT_ROOT}/2012%{REQUEST_URI} -f
RewriteRule .* 2012/$0 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* 2012/index.php?q=$0 [QSA]
The new condition RewriteCond %{REQUEST_URI} ^/index\.php [OR] will be satisfied if a request is made starting with /index.php and the URI gets rewritten as-is into the /2012/ directory. The [OR] ensures the previous condition of a direct access be honored.