I'm looking to create a multi-tenant project with the address structure as follows
https://example.com/TENANTNAME/file.php
https://example.com/TENANTNAME/api/file.php
https://example.com/TENANTNAME/assets/js/main.js
And have it rewrite to a single subfolder, say /BASE/ - the idea being I can have a single set of files and then inspect the URL to figure out the rest.
Thank you
I did get it working to a point with the following, but further subfolders (Edited from subdomains) were not properly redirected, so the main index.php was fine but any anything in the assets folder was giving a server error
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/BASE/(.*)/
RewriteRule ^(.*)/(.*)$ /BASE/$2 [L]
As an example, I would expect the following internal rewrites
https://example.com/TENANTNAME/index.php
to
https://example.com/BASE/index.php
https://example.com/TENANTNAME/assets/js/main.js
to
https://example.com/BASE/assets/js/main.js
The index.php example did work with my attempt however the assets example, with further subfolders, did not
My first question was "Could the wildcard folders exist on the disk?"
If yes, then the first two rewrite conditions could potentially stop the rewrite rule to execute when a request matches an existing file or directory.
So I think you can remove these conditions, as you probably don't need them.
The next rewrite condition, testing that it's not the /BASE/
root
directory, should be sufficient. But it can be slightly optimized by
replacing
RewriteCond %{REQUEST_URI} !^/BASE/(.*)/
By
RewriteCond %{REQUEST_URI} !^/BASE/
We don't need to capture what's behind the second slash. It actually
creates a variable called %1
that can be used in the rewrite rule
destination URL. But in any case, we have some other capturing
groups in the rewrite rule pattern.
They might be a little problem of greediness in the regex of the
rewrite rule. ^(.*)/
could be capturing to many characters,
leading to capturing some other slashes. So there are two solutions
to solve it:
Make it ungreedy by adding a question mark: ^(.*?)/
By the way, I would replace the *
by +
because we want to
match at least one char.
Instead of the dot, use "not a slash": ^([^/]+)/
This has a big advantage because we know that a folder should not
contain slash characters. The regex should run faster than the
ungreedy version above and will also be safer.
Also, I thought that your PHP scripts might like to know what
was the original URL before the rewrites. You can get this
information by reading the $_SERVER
array but why not converting
it to a query parameter as we captured it in any case? This can be
achieved this way:
RewriteRule ^([^/]+)/(.*)$ /BASE/$2?original_root=$1 [L,QSA]
The first capturing group is $1
and can be added at the end of the
URL, as a query parameter. By the way, the rewrite rule pattern is
applied on the path without the query string (which is normally
added back to the destination URL). But here, as I am creating a
new query string, I have to enable the QSA
option which will
append the original query string to the newly created one.
(QSA = query string append).
This way, an URL like:
/any-folder/something/script.php?id=6&op=view
should become:
/BASE/something/script.php?original_root=any-folder&id=6&op=view