Mod rewrite into subdirectory - mod-rewrite

I have been having some trouble getting the following to work:
<IfModule mod_rewrite.c>
DirectoryIndex index.php
Options +FollowSymLinks
RewriteEngine On
# If the file is not found in web
RewriteCond web/$1 -f [NC] #<-- This line seems to be the problem.
RewriteRule ^(.*)$ web/$1 [L]
# Then rewrite it to index.php
RewriteRule ^(.*)$ index.php [L,QSA]
</IfModule>
The idea is to check if the file exists in the web directory, and if it doesn't, route the request to index.php.
The problematic line above seems to pick up the correct URL, but it does not recognize that the file exists.
For example:
http://localhost/img.gif --> /www/web/img.gif
http://localhost/subdir/file.doc --> /www/web/subdir/file.doc
http://localhost/user/add --> /www/index.php
http://localhost/invalidurl --> /www/index.php
However, I cannot get static resources to be served correctly, they are all routed to index.php.
I also want to keep all URLs relative; so I can make this code reusable without editing it.
The following .htaccess gives an Internal Server Error, if I visit img.gif:
<IfModule mod_rewrite.c>
DirectoryIndex index.php
Options +FollowSymLinks
RewriteEngine On
# If the file is not found in web
#RewriteCond web/$1 -f [NC] #<-- This line seems to be the problem.
RewriteRule ^(.*)$ web/$1 [L]
# Then rewrite it to index.php
#RewriteRule ^(.*)$ index.php [L,QSA]
</IfModule>
This .htaccess redirects to http://localhost/C:/absolute/path/to/web/img.gif, when visiting img.gif:
<IfModule mod_rewrite.c>
DirectoryIndex index.php
Options +FollowSymLinks
RewriteEngine On
# If the file is not found in web
#RewriteCond web/$1 -f [NC] #<-- This line seems to be the problem.
RewriteRule ^(.*)$ web/$1 [R]
# Then rewrite it to index.php
#RewriteRule ^(.*)$ index.php [L,QSA]
</IfModule>
My conclusion from this would be that it's getting the path correct, but some weirdness is causing it to do something completely weird (I don't even know why it has an internal server error - Should be 404 not found).

Ok I got it:
When you do a rewrite, then keep in mind that the rewritten URL is called internally.
So you basically have to reprocess the .htaccess with mostly different values.
So in your example : http://localhost/img.gif is directed to http://localhost/web/img.gif and then to http://localhost/index.php by the last rule.
I would try this (replace the last rule by: )
RewriteCond %{SCRIPT_NAME} !^/web/
RewriteRule ^(.*)$ index.php [L]
(NB: [QSA] is not needed since you don't touch the query string, so it is passed as is.)
Edit : What about
# If the file is not found in web
RewriteCond web/$1 !-f [NC]
# And we don't ask for /web/something at the beginning (Avoid infinite loops since you'll try to call web/image.gif and we don't want to test /web/web/image.gif and fail to index.php
RewriteCond %{SCRIPT_NAME} !^/web/
#Rewrite it to index.php
RewriteRule ^(.*)$ index.php [R,L]
# If the file is found in web
RewriteCond web/$1 -f [NC]
# And we don't ask for /web/something at the beginning (Avoid infinite loops since you'll try to call web/image.gif and we don't want to test /web/web/image.gif and fail to index.php
RewriteCond %{SCRIPT_NAME} !^/web/
#Then point to web/image.gif
RewriteRule ^(.*)$ web/$1 [L]

Related

how to allow /.well-known/security.txt in htaccess

I want to whitelist this file only in .well-known directory .
My htaccess file
Options -Indexes
RewriteEngine on
RewriteCond %{REQUEST_URI} !^public
RewriteRule ^(.*)$ public/$1 [L]
<IfModule mod_rewrite.c>
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule "(^|/)\." - [F]
</IfModule>
my attempts
<Files .well-known/security.txt>
Allow from all
Satisfy Any
</Files>
RewriteEngine on
RewriteCond %{REQUEST_URI} !^(public|.well-known/security.txt)
RewriteRule ^(.*)$ public/$1 [L]
Conclusion !
I just want to whitelist security.txt file only in .well-known directory
RewriteCond %{REQUEST_URI} !^public
RewriteRule ^(.*)$ public/$1 [L]
This condition is in error since the REQUEST_URI server variable always starts with a slash, so the expression !^public is always successful.
(From this I assume you must have another .htaccess file in the /public subdirectory, otherwise you would get a rewrite loop.)
Once you realise this then you can modify the rule in the way you had tried. For example:
RewriteCond %{REQUEST_URI} !^/(public|\.well-known/security\.txt$)
RewriteRule ^(.*)$ public/$1 [L]
HOWEVER, your other rule blocks all requests for physical files/directories that start with a dot, so the request will still be blocked (with a 403 Forbidden). This rule is also in the wrong place for other requests (it needs to be before the rewrite to the /public subdirectory).
You are better off making an exception as a separate rule at the start of the file instead. For example, try the following instead:
Options -Indexes
RewriteEngine on
# Prevent further processing for special files
RewriteRule ^\.well-known/security\.txt$ - [L]
# Block access to all dot-files
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule (^|/)\. - [F]
# Rewrite request to "/public" subdirectory
RewriteCond %{REQUEST_URI} !^/public
RewriteRule (.*) public/$1 [L]
The <IfModule> wrapper on that one rule was superfluous.

Is there any changes required in the .htaccess file to acces the API routes?

I have added a few routes to the api.php file. These routes are working perfectly in the localhost environment.
http://localhost/api/v1/events
gives desired output but when uploaded to the production/remote server I cannot access it using the domain name.
http://domainname/api/v1/events
throws an 404 error. I am using the same .htaccess files in the localhost as well as in the prod/remote server. I am not sure why is it not working correctly in the prod/remote server.
By the way, I have web routes which works fine in both the environments. My .htaccess file is copied below.
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Modified .htaccess as per the answer but it is not working for me :(
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# API
RewriteRule ^api/(.*) api.php/$1 [L]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Tried this as well.
RewriteRule ^api/(.*) routes/api.php/$1 [L]
Can anyone help by advising what is wrong?
My root folder
the folder in which api.php is available
The confusing part about this is that you say it works "perfectly in the localhost", yet you are using the same .htaccess file in both environments. This cannot work on localhost unless you have some other directives somewhere since there is nothing that would rewrite such a request to /api.php.
To enable this, and pass the additional path information as path-info to api.php, then you would need to add something like the following after the # Handle Authorization Header rule:
# API
RewriteRule ^api/(.*) api.php/$1 [L]
This would internally rewrite a request of the form /api/v1/events to /api.php/v1/events, allowing api.php to read /v1/events from the $_SERVER['PATH_INFO'] superglobal.
Without this directive (and with MultiViews being disabled) a request of the form /api/v1/events would be routed through index.php instead where I assume the "route" is not defined, hence the 404.
UPDATE#1: No my /api.php is under the same directory which has web.php, that is routes
In that case, you need to modify the above rule to read:
RewriteRule ^api/(.*) routes/api.php/$1 [L]
UPDATE#2: from your updated URL structure, it seems that /routes is actually under /myprojectfolder in the document root (where the .htaccess and index.php files are located), so you would need to modify the above to account for this. For example:
RewriteRule ^api/(.*) myprojectfolder/routes/api.php/$1 [L]
However, it seems that a direct request for /myprojectfolder/routes/api.php/v1/events does not work anyway, so passing this as path-info would not seem to be the correct course of action to begin with.

Removing index.php and handling subdomains of two Codeigniter sites, when one within the other

I have two Codeigniter sites, one sitting within the subdirectory of the other. I need some help modifying my htaccess file to remove index.php from both.
The first site, http://subdomain.domain.com is stored in /home/sites/subdomain/www/html/
The second, http://test.subdomain.domain.com lives in /home/sites/subdomain/www/html/app_staging/
This is my .htacess file from /home/sites/subdomain/www/html/:
RewriteEngine On
# Rewrite the main domain
RewriteCond %{HTTP_HOST} !test.subdomain.domain.com
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?/$1 [L]
# Rewrite the sub domain
RewriteCond %{HTTP_HOST} test.subdomain.domain.com
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(.*)$ /app_staging/index.php?/$1 [L]
This is removing index.php from the from the first site, everything is ok there. On the second site, I can load the default controller form http://test.subdomain.domain.com, but subsequent pages return a 404 from the server. What are my next steps?
You should put each of two .htaccess files inside their own root CI folder.
Personally, I prefer restricting requested files and/or folders in order to prevent them from being treated by RewriteRule.
So, for the first file which is located at /home/sites/subdomain/www/html/:
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine on
RewriteCond $1 !^(index\.php|robots\.txt|favicon\.ico|public)
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
And for the other one is located at /home/sites/subdomain/www/html/app_staging/:
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine on
RewriteCond $1 !^(index\.php|robots\.txt|favicon\.ico|public)
RewriteRule ^(.*)$ /app_staging/index.php/$1 [L]
</IfModule>
Note: You must add css and other folders (like public) to RewriteCond if you don’t want them to be treated by RewriteRule.
As a side-note: You might want to prevent directory listing by using the following inside each .htaccess file:
<IfModule mod_autoindex.c>
Options -Indexes
</IfModule>

AJAX rewrite rule for directories

I'm trying to write a rewrite rule in addition to wordpress's :
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
I would not like everything to redirect to the main page. I have multiple sub-directories which need to be redirected too : http://www.example.com/sub1 and http://www.example.com/sub2. I'm doing this so my content can be loaded via Ajax.
I thought this would simply be
RewriteRule ^/(sub1|sub2)/(.*)$ http://www.example.com/$1/ [L]
Which I placed in the block here:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(sub1|sub2)/(.*)$ http://www.example.com/$1/ [L]
RewriteRule . /index.php [L]
</IfModule>
Perhaps with wordpress you must use wp_rewrite_rule? I figured I could mess with the .htaccess file, get my rule to work, then move it over to functions.
any help would be appreciated.
Thanks.
UPDATE:
I've also tried to set the .htacces file back to the wordpress default... and add this code to the functions.php file for my child theme:
function AJAX_rewrite_rule() {
add_rewrite_rule(
'^/(sub1|sub2)/(.*)$',
'http://www.example.com/$1',
'top' );
};
add_action( 'init', 'AJAX_rewrite_rule' );
Seems to slow the load of everything down, but all files not found are still redirected to the main page, not the subdirectory.
UPDATE #2
I think I was going the wrong direction, as add_rewrite_rule is only to add a rule to the structure already put in place by wordpress. This all works by interpreting URL's, and changing them to variables for a DB query run by index.
I'm pretty sure I need to use $wp_rewrite->non_wp_rules. If anyone has more of an idea, let me know.
Try this, you seem to have ine bad line there:
<IfModule mod_rewrite.c>
RewriteEngine On
# RewriteBase /
# RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f #Means DONT redirect if file exists.
RewriteCond %{REQUEST_FILENAME} !-d #Means DONT redirect if directory exists.
RewriteCond %{REQUEST_URI} !^/sub1/
RewriteCond %{REQUEST_URI} !^/sub2/
# RewriteRule ^/(sub1|sub2)/(.*)$ http://www.example.com/$1/ [L]
RewriteRule . /index.php [L]
</IfModule>
What happens is, every time you add a "RewriteRule" all the "RewriteCond" are applied to that rule, and then you start with a blank slate:
RewriteCond A
RewriteCond B
RewriteCond C
RewriteRule Whatever [L] #This applies A, B, and C
RewriteRule Another [L] #This applies no rules
Perhaps that will help.
Also, you may try adding your "RewriteRule ^/(sub1|sub2)/(.*)$ http://www.example.com/$1/ [L]" right after "RewriteEngine On" if that doesn't work…

mod_rewrite but skip a directory

I'm attempting to avoid urls like this one:
images/
or
images/valid-filename.png
or
images/invalid-filename.png
from being rewritten
and I've checked other example questions like .htaccess mod_rewrite on root directory but need it to skip all other directories and .htaccess mod_rewrite exemptions and this one https://stackoverflow.com/questions/7209746/can-mod-rewrite-skip-a-folder but I've not managed to get the rules to achieve what I'm after.
Here is what I have right now:
# Enable URL Rewriting
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^(scripts|styles|images)(/.*|$) - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/robots.txt
RewriteCond %{REQUEST_URI} !=/favicon.ico
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# This solved the problem
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RewriteCond %{REQUEST_URI} !images/.* [NC]
RewriteRule ^(.*)$ index.php [L,QSA]
</IfModule>
If I navigate to www.site.com/images/, I get redirected to www.site.com
If I navigate to www.site.com/images/invalid-filename.png, I get redirected to www.site.com
but www.site.com/images/valid-filename.png loads correctly.
Could someone help to explain how to achieve the rewrite behaviour described above?
Many thanks
Try adding this RewriteCond: RewriteCond %{REQUEST_URI} !images/.* [NC]
It will check whether the URI begins with images/ and if it does, the rule will not be met.

Resources