Reputation: 330
I have a subdomain called test.mysite.com
and I have a CI4 installation inside a folder there called project. So the actual url for the CI4 installation is test.mysite.com/project/public/index.php
. I want to remove the public/index.php portion from the url but continue to use the public folder to have my files, as they should.
I'm using this .htaccess on the project folder root:
DirectoryIndex /public/index.php
RewriteEngine on
RewriteCond $1 !^(index\.php|images|assets|css|js|robots\.txt|favicon\.ico)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ ./public/index.php/$1 [L]
<IfModule mod_headers.c>
<FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font.css|css|js)$">
Header set Access-Control-Allow-Origin "*"
</FilesMatch>
</IfModule>
But it's not working. When I access test.mysite.com/project it leads me to a server list of files. I know the .htaccess file is being properly read because when I add an error there it gives me a warning
EDIT: CI4 already comes with an htaccess inside the public folder:
# Disable directory browsing
Options All -Indexes
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine On
# If you installed CodeIgniter in a subfolder, you will need to
# change the following line to match the subfolder you need.
# http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritebase
# RewriteBase /
# Redirect Trailing Slashes...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Rewrite "www.example.com -> example.com"
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
# Checks to see if the user is attempting to access a valid file,
# such as an image or css document, if this isn't true it sends the
# request to the front controller, index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([\s\S]*)$ index.php/$1 [L,NC,QSA]
# Ensure Authorization header is passed along
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>
<IfModule !mod_rewrite.c>
# If we don't have mod_rewrite installed, all 404's
# can be sent to index.php, and everything works as normal.
ErrorDocument 404 index.php
</IfModule>
# Disable server signature start
ServerSignature Off
# Disable server signature end
Upvotes: 4
Views: 12142
Reputation: 550
Working for years with Codeigniter 3 I had this issue too. First I tried the .htaccess
road but after realizing Codeigniter 3 could also benefit from a more secure structure, I applied the same experience to Codeigniter 4.
The basic idea is to move the whole framework to a folder off the web root. And move the public folder to the root (WEBROOT can also be a subfolder under the public html folder)
PRIVATEFOLDER
\codeigniter:
\app
\vendor
\writable
WEBROOT
assets\
index.php
.htaccess
Then I'll modify index.php (and spark and preload.php if used). This will do in index.php:
// This is the line that might need to be changed... etc
define('ENGINEPATH', 'PRIVATEFOLDER/codeigniter');
require ENGINEPATH . '/app/Config/Paths.php';
And /app/Config/Paths.php to this:
namespace Config;
class Paths
{
public $systemDirectory = ENGINEPATH . '/vendor/codeigniter4/framework/system';
public $appDirectory = ENGINEPATH . '/app';
public $writableDirectory = ENGINEPATH . '/writable';
public $testsDirectory = ENGINEPATH . '/tests';
public $viewDirectory = ENGINEPATH . 'app/Views';
}
Now, set the $baseURL to the WEBROOT url and you should be able to navigate without index.php and public, and the app code is protected outside the public folder.
Upvotes: 0
Reputation: 45829
When I access test.mysite.com/project it leads me to a server list of files
Because your DirectoryIndex
is set to /public/index.php
(which presumably does not exist, as the index document is located at /project/public/index.php
) and directory indexes (mod_autoindex) is presumably enabled (it should be disabled, so that such a request results in a 403 Forbidden).
the difference is that the other website that is working is not on a subdomain and it’s on the root, so it’s not the same htaccess
I'm not sure why it would be any different?
With the .htaccess
file in the /project
subdirectory, arrange your mod_rewrite (and mod_dir) directives like this instead:
DirectoryIndex index.php
Options -Indexes
RewriteEngine on
RewriteCond $1 !^public/(index\.php|images|assets|css|js|robots\.txt|favicon\.ico)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) public/index.php/$1 [L]
The presence of robots\.txt
and favicon\.ico
in the first condition implies you are rewriting requests from the document root. Since search engines request /robots.txt
(in the document root), not /project/robots.txt
(or /project/public/robots.txt
). The same applies to /favicon.ico
. If you are not rewriting these two requests then these two entries are not required.
This also assumes you are linking directly to your static resources using the public
subdirectory. eg. /projects/public/images/foo.jpg
. This isn't necessarily desirable since it exposes /public
in the URL path. Users won't necessarily see this as it's not directly visible in the browser's address bar, but search engines and anyone who views the HTML source / network traffic will see it.
Just to add, that first condition (ie. RewriteCond
directive) is "just" an opimisation. If it's set incorrectly, your site will probably work OK and you won't see a difference, except that it will be performing many more filesystem checks than it needs to do.
An alternative approach is to have two .htaccess
files. A basic /project/.htaccess
file that simply rewrites everything to the public
subdirectory and a more comprehensive (CI) .htaccess
file at /project/public/.htaccess
that actually routes the request to CI. This then allows you to omit public
from all URLs, including URLs to your static resources.
For example:
/project/.htaccess
DirectoryIndex index.php
Options -Indexes
RewriteEngine On
# Unconditionally rewrite everything to the "public" subdirectory
RewriteRule (.*) public/$1 [L]
/project/public/.htaccess
The presence of mod_rewrite directives in the subdirectory .htaccess
file naturally prevent a rewrite loop from the RewriteRule
directive in the parent directory. (Assuming mod_rewrite inheritance has not been enabled.)
RewriteEngine on
RewriteCond $1 !^(index\.php|images|assets|css|js|robots\.txt|favicon\.ico)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php/$1 [L]
<IfModule mod_headers.c>
<FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font.css|css|js)$">
Header set Access-Control-Allow-Origin "*"
</FilesMatch>
</IfModule>
Upvotes: 10