.htaccess redirect based on folder - apache

I need help with .htaccess Rewrite rules.
I have a API which can be accessed over http://api.my.domain/products/all which is working fine and is returning result.
I would like to redirect users coming to http://api.my.domain/admin to admin folder.But it is not working with current rules.
I have added this to .htaccess but it is not working correctly for admin folder.
RewriteEngine On
RewriteCond %{Request_Filename} !-F
RewriteCond %{Request_Filename} !-d
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^admin admin/index.php [QSD,L]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^ public/index.php [QSD,L]
This is the result I get when I enter http://api.my.domain/admin and is breaking all my php redirects:
http://api.drezga.hr/admin/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/admin/admin/checklogin.php
Can someone, please, tell me what I'm doing wrong? I have spent hours and I can't see it.

Aside: If /admin is a physical directory then you should be requesting /admin/ (with a trailing slash) to begin with, otherwise Apache/mod_dir will issue a 301 redirect to append the trailing slash.
RewriteCond %{Request_Filename} !-F
RewriteCond %{Request_Filename} !-d
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^admin admin/index.php [QSD,L]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^ public/index.php [QSD,L]
The first two conditions (RewriteCond directives) are being applied incorrectly to the first rule only. They need to apply to the last rule (the rewrite to public/index.php) then the rewrite to admin/index.php is not necessary (this should be handled by the DirectoryIndex).
There's no need for the QSD flag since you are checking that the query string is already empty - there is no query string to discard!
You should probably be using the -f operator on the condition, not -F (which uses subrequests and is consequently less efficient).
Try the following instead:
DirectoryIndex index.php
RewriteEngine On
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Optimisation (prevent additional filesystem check)
RewriteRule ^public/index\.php$ - [L]
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . public/index.php [L]
RewriteRule ^$ public/index.php [L]
The RewriteCond %{REQUEST_FILENAME} !-d directive prevents requests for /admin/ being passed to public/index.php.
The additional RewriteRule at the end is to rewrite requests for the root directory, which would otherwise be omitted because of the condition mentioned above. This could be avoided by extending the DirectoryIndex directive instead, although this could change the behaviour if you have other directories that need to be accessible (or should not be routed to public/index.php). For example:
DirectoryIndex index.php /public/index.php

Related

.htaccess - remove everything after third slash in path

On my website, I only use 3 slashes in my URL path:
https://example.com/this/isatest/
Right now I use .htaccess which makes it possible (as a side effect) to add as many stuff on the URL as you like:
https://example.com/this/isatest/hipperdihopperdus/pizza/bacon/with/cheese
I'd like to automatically remove everything after "isatest" while keeping the trailing slash using .htaccess.
This is what my .htaccess currently looks like:
Options -Indexes
Options +FollowSymLinks
RewriteEngine on
# 301 Redirect all requests that don't contain a dot or trailing slash to
# include a trailing slash
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{REQUEST_URI} !\.
RewriteRule ^(.*) %{REQUEST_URI}/ [R=301,L]
RewriteCond %{THE_REQUEST} /index\.html [NC]
RewriteRule ^index\.html$ /? [R=301,L,NC]
RewriteRule ^listen/$ /console/ [NC,L]
# Rewrites urls in the form of /parent/child/
# but only rewrites if the requested URL is not a file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?page=$1 [L,QSA]
How can I achieve this?
As your first rule, after the RewriteEngine directive, you can do something like the following:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+/[^/]+/). /$1 [R=302,L]
This checks if there is anything else (the dot) after two path segments and a slash, and redirects to removed "anything else".
Note that this is a 302 (temporary) redirect. Only change this to a 301 (permanent) redirect - if that is the intention - once you have confirmed that it works OK. This is to avoid the browser caching erroneous redirects whilst testing.
UPDATE: It may be more efficient to simply avoid redirecting files that end in a recognised file extension. Or perhaps exclude known directory location(s) of your static resources. For example:
RewriteCond %{REQUEST_URI} !\.(css|js|jpg|png|gif)$ [NC]
RewriteRule ^([^/]+/[^/]+/). /$1 [R=302,L]
OR,
RewriteCond %{REQUEST_URI} !^/static-resources/
RewriteRule ^([^/]+/[^/]+/). /$1 [R=302,L]
You can add this rule just below RewriteEngine On line:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+/[^/]+/).+$ /$1 [R=301,L,NE]

mod_rewrite Rules Giving 404

I'm sure this has been answered, I've been reading for a few hours now and am getting nowhere. I need this to work tonight and my brain is hurting, so I'm asking the the wonderful internet for help.
I'm trying to run all my pages through index_new.php (it all made sense when I decided to do that, I swear). I have two types of pages, static and dynamic. The dynamic pages are all the same kind of page, but with different data based on the database (MySQL). I'm trying to make these rewrites
/about => index_new.php?page=about
/installations => index_new.php?page=about
/installations/{site_id} => index_new.php?page=site&siteID={site_id}
(I'd love if about could be generic, but I don't want to push my luck) My .htaccess file is:
# enable rewrite
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
# rewrite all physical existing file or folder
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d
# allow things that are certainly necessary
RewriteCond %{REQUEST_URI} "/statics/" [OR]
RewriteCond ${REQUEST_URI} "/ajax/"
# rewrite rules
RewriteRule ^about index_new.php?page=about
RewriteRule ^/installations index_new.php?page=list
RewriteRule ^/installations/(.*) index_new.php?page=site&id=$1
When I try to go to /about or any other page, I get HTTP 404. As a note, my root is http://localhost/~user/public_html/new and the .htaccess file is there.
Provided:
The conditions in the question have to be met for each rule. (They are repeated as they are valid only for the next rewrite rule).
The .htaccess file is located at root.
You may try this instead of the rule-set in your question:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /about/?$ [NC]
RewriteRule .* /index_new.php?page=about [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /installations/?$ [NC]
RewriteRule .* /index_new.php?page=list [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /installations/([^/]+)/? [NC]
RewriteRule .* /index_new.php?page=site&id=%1 [NC,L]
Maps silently:
http://example.com/about to
http://example.com/index_new.php?page=about
http://example.com/installations to
http://example.com/index_new.php?page=about
http://example.com/installations/Anything to
http://example.com/index_new.php?page=site&Anything
For permanent and visible redirection, replace [NC,L] with [R=301,NC,L].
NOTE:
These conditions in the question were not used as their purpose is not clear:
RewriteCond %{REQUEST_URI} "/statics/" [OR]
RewriteCond ${REQUEST_URI} "/ajax/"
To include them for one or several rules, try this:
# For NOT condition, include the next line before the corresponding rewrite rule:
RewriteCond %{REQUEST_URI} !(statics|ajax) [NC]
# For positive condition, include the next line before the corresponding rewrite rule:
RewriteCond %{REQUEST_URI} (statics|ajax) [NC]

mod_rewrite rules in .htaccess

I want to do change my document root using rewrite rules in my .htaccess file, and also redirect all requests to index.php except static resources
In other words:
if a file with the path prepended with www exists (i.e. www/{%request_uri}):
http://domain.com/css/main.css should be rewritten to http://domain.com/www/css/main.css
if that file does not exist, redirect to the app main entry point www/index.php:
e.g.
http://domain.com should be rewritten to http://domain.com/www/index.php
http://domain.com/hello should be rewritten to http://domain.com/www/index.php/hello
http://domain.com/hello?a=1 should be rewritten to http://domain.com/www/index.php/hello?a=1
I tried variations, however either it gives us 500 internal server error, or infinite loop. Here is one that gives 500 internal server error:
# try to find it in www/
RewriteCond {%DOCUMENT_ROOT}/www%{REQUEST_URI} -f
RewriteCond {%DOCUMENT_ROOT}/www%{REQUEST_URI} -d
RewriteRule ^(.+) www/$1 [L]
RewriteRule ^(.*) www/index.php/$1 [L]
This one also:
RewriteCond %{REQUEST_URI} !www/
RewriteRule (.*) /www/$1
RewriteCond {%REQUEST_FILENAME} !-f
RewriteCond {%REQUEST_FILENAME} !-d
RewriteRule www/(.*) /www/index.php/$1 [PT,L]
Can anyone help?
I think that's impossible with a single .htaccess but it's possible with two.
You need one in your root directory, /.htaccess:
RewriteEngine on
RewriteBase /
# We don't want infinite rewriting.
RewriteCond %{REQUEST_URI} !www/.*$
RewriteRule ^(.*)$ www/$1 [L]
And another in your www directory, /www/.htaccess:
RewriteEngine on
RewriteBase /www
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
Well actually I made a stupid mistake! The % sign should be outside of the {} bracket!
This can be done in one .htaccess in root dir:
RewriteEngine on
RewriteCond %{REQUEST_URI} !www/
RewriteRule ^(.*)$ www/$1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^www/(.*)$ www/index.php/$1 [L]

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

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.

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.