.htaccess Issues, Virtual Subdomains & Codeigniter - apache

basically my problem is this. I have set up a system that accepts wildcard subdomains, and rewrites them to a single CodeIgniter installation. There is a controller called dispatcher that takes the arguments that it requires, as well as being passed the subdomain being used in the URL.
My problem is this: I need to create RewriteRules that conform with CodeIgniter's URL structure. Currently I have this:
RewriteEngine On
# Extract the subdomain part of domain.com
RewriteCond %{HTTP_HOST} ^([^\.]+)\.ev-apps\.com$ [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# Check that the subdomain part is not www and ftp and mail
RewriteCond %1 !^(www|ftp|mail)$ [NC]
# Redirect all requests to a php script passing as argument the subdomain
RewriteRule ^/(.*)/(.*)$ /dispatcher/run_app/$1/$2/%1 [L,QSA] # First is app name, then site, then action
RewriteRule ^/(.*)/(.*)/(.*)$ /dispatcher/run_app/$1/$2/$3/%1 [L,QSA] # First is app name, then site, then action, then any passed data.
It works fine for URLs that follow this format "http://example.ev-apps.com/app/method/1", but not for "http://example.ev-apps.com/app/method". It seems the precedence is all wrong, but ideally I want a solution that will work for any number of segments, for example: "http://example.ev-apps.com/app/method/1/2/3/4/5/6/7/8/9, etc.
Any help would be greatly appreciated.

I solved this issue by using the following directive:
RewriteRule ^(.*)$ /dispatcher/run_app/%1/$1 [L,QSA]
And then using the following code in my dispatcher action:
$args = func_get_args();
$site_subdomain = $args[0];
$app_name = $args[1];
$action = $args[2];
$input = (isset($args[3]) ? $args[3] : '');
Thanks for reading, if you did!

Related

Moving from IIS ISAPI rewrite to Apache mod_rewrite

I've seen few people have asked this on here already, but none of the solutions provided worked for me so far.
We have always been developing for the IIS ISAPI rewrite (on Windows) and suddenly one of the clients decided to place the project on the Linux server running Apache. As a result some of the rules are no longer working.
Example of an ISAPI rewrite rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^login/?([^/]*)([^/]*)$ /login.cfm?msg=$1&$2 [L,QSA]
RewriteRule ^login.cfm$ /login/ [R=301,L,NC]
login.cfm is an actual existing page and not dynamically generated based on template.
Could someone help me how to translate this for the Apache mod_rewrite please? Currently the rule creates an infinitive loop and the output is:
login/?msg=&&msg=&&msg=&&msg=&&msg=&&msg... (till the limit of the url length)
Safe to say the page is not found either so it doesn't even check whether the file with such name exists.
The page could be /login or /login/wrong so the rule should recognize both cases.
You can use these rules in your site root .htaccess:
RewriteEngine On
# external redirect from actual URL to pretty one
RewriteCond %{THE_REQUEST} /login\.cfm\?msg=([^\s&]*)\s [NC]
RewriteRule ^ /login/%1? [R=301,L,NE]
# internal forward from pretty URL to actual one
RewriteRule ^login(?:/([\w-]+))?/?$ login.cfm?msg=$1 [L,QSA,NC]

Redirect URL (including port) with params using .htaccess

I am trying to redirect from
http://www.example.com:81/my/api/search?query=test
to
http://www.example.com:81/my/php/api.php?query=test
using
RewriteCond %{QUERY_STRING} ^query=(.*)$
RewriteRule ^api/search(.*)$ /php/api.php?%1 [L]
However, it doesn't work for me. Additionaly for testing htaccess rules I use http://htaccess.madewithlove.be/.
Possibly even better would be to check if request starts from ^api and it's GET type (I guess using RewriteCond %{REQUEST_METHOD}) then redirect to /my/php/api.php?[query params here]
Anyone can point me into right direction?
If your .htaccess is located in /my/ directory then you can use:
RewriteEngine On
RewriteBase /my/
RewriteCond %{QUERY_STRING} ^query=.
RewriteRule ^api/search/?$ php/api.php [L]
QUERY_STRING will be automatically carried over to target URL.

Apache RewriteRule pass entire URL as a parameter

Currently my Apache RewriteRule only passes the path of the original URL as a query parameter to the rewritten URL.
How do I send the entire URL (including scheme and authority etc) as a parameter to the rewritten URL?
I know %{REQUEST_URI} only passes the path, and I can’t see any Apache environment variables that do pass the entire URL.
I’m something of a beginner to Apache configuration so excuse any ignorance on my part,
thanks!
Here’s my current config:
#
# Enable Rewrite
#
RewriteEngine On
#
# Condition for rewriting the URL. Check the URL's path is a valid REST URI path
#
RewriteCond %{REQUEST_URI} ^(?:[^?#]*)(?:/v[0-9]+(?:\.[0-9]+)*)(?:/[a-z]+)(?:/[a-z]+)(?:/?[^/?#]*)(?:[^?#]*)$
#
# Rewrite the URL, sending the REST path as a parameter to the specified version.
#
RewriteRule ^(?:[^?#]*)(?:/(v[0-9]+(?:\.[0-9]+)*))((?:/[a-z]+)(?:/[a-z]+)(?:/?[^/?#]*)(?:[^?#]*))$ https://localhost/rest/$1/index.php?request_uri_path=https://localhost/rest/$1/$2 [QSA,NC,L,R=307]
Currently I’ve hardcoded the url into the query parameters so the URL
https://localhost/rest/v1/users/show/12345
becomes:
https://localhost/rest/v1/index.php?request_uri_path=https://localhost/rest/v1/users/show/12345
You can use this rule to get full URL as query parameter:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{HTTPS}s on(s)|
RewriteRule ^ index.php?request_uri_path=http%1://%{HTTP_HOST}%{REQUEST_URI} [L,QSA]
If you're on Apache 2.4 then you can make use of %{REQUEST_SCHEME} variable:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php?request_uri_path=%{REQUEST_SCHEME}://%{HTTP_HOST}%{REQUEST_URI} [L,QSA]

URL Rewriting using .htaccess

To change the URL /mobiles.php?id=5 to /mobiles/5
The content of .htaccess file is as follows:
Options +FollowSymlinks
RewriteEngine on
RewriteRule /mobiles/$1 ^/mobiles.php?id=([0-9]+)$
But still it is showing /mobiles.php?id=5 in the address bar. Please help. Is there anything else needs to be added in the .htaccess file?
Note:
mod_rewrite module is enabled
I have restarted Apache server after making changes to the .htaccess
file
.htaccess file is in htdocs folder of Apache.
I am using Windows + PHP + Apache + MySQL
This works for me:
Options +FollowSymlinks
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^mobiles/([0-9]+)$ mobiles.php?id=$1&rew [L]
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
RewriteRule ^mobiles.php$ /mobiles/%1? [R,L]
If you see this line:
RewriteRule ^mobiles/([0-9]+)$ mobiles.php?id=$1&rew [L]
I have added rew variable in the query string to prevent Apache to fall in an infinite loop
When Apache execute this line:
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
Is to make sure that url has not been rewritten for Apache
If your only concern is that the old url stays in the address bar, and you want this not to happen, try adding an [R] at the end.
RewriteRule ^/mobiles.php?id=([0-9]+)$ /mobiles/$1 [R]
Did you actually see the correct page?
By the way, the rewrite rules generally go the other way. I would be expecting to see something like:
RewriteRule ^/mobiles/([0-9]+)$ /mobiles.php?id=$1
Is your concern one of making sure a URL with query parameters does not show up in the address bar?
If I understand correctly, you want
Internally redirect /mobiles/5 to /mobiles.php?id=5
Also redirect the browser TO /mobiles/5 if a user navigates to /mobiles.php?id=5
For this you need 2 rules one to internally rewrite the URL for 1st case and 2nd for browser redirection.
You can do it like this:
RewriteEngine on
# for internal rewrite
RewriteRule ^/?mobiles/([0-9]+)/?$ /mobiles.php?id=$1 [L]
# for browser redirect
RewriteRule ^/?mobiles\.php\?id=([0-9]+)$ /mobiles/$1/ [R,L]
You are doing the opposite, should be:
RewriteRule ^/something/mobiles/([0-9]+)$ /something/mobiles.php?id=$1

Apache Rewrite Issue, Custom URI

I have a solution but it is one that I know is not the greatest and would better be solved with a full rewrite. Basically I have 3 rewrites that will go to the correct areas I want and do what they need to do. However in order to switch between where I need to go I had to write a URI class to strip through the url set the page and vars manually. It all works out great but the urls are a pain in the ass specially if not formatted exactly.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/bsiadmin/$ /bsiadmin/index.php [L,QSA]
RewriteRule ^/bsiadmin/(.+)/$ /bsiadmin/index.php?page=$1 [L,QSA]
RewriteRule ^/(.+)/$ /index.php?page=$1 [QSA]
So the first rule will make sure to direct everything to the directory and not the root index.php, the second rule does the same if there is a "page" specified. The last rule will take anything else and make sure it uses the root index.php and goes from there.
Example of urls:
http://mysite.test/icecream/id=2/
My custom uri class would strip this clean and set id as a $_REQUEST var.
I guess what I really want to know is how can I just rewrite a simple url such as:
http://mysite.test?page=icecream&id=2
AS
http://mysite.test/icecream/id/2/
Without any limitation on how many vars can be passed and the directory that does exist "bsiadmin" to display without me having to use a uri class to direct it.
Thanks for the help.
You can use mod_rewrite to do so:
RewriteRule ^/([^/]+)/([^/]+)/([^/]+)/(.*) /$1/$4?$2=$3 [N,QSA]
RewriteRule ^/([^/]+)/$ /bsiadmin/index.php?page=$1 [L,QSA]
But I think the best would be to use PHP for that job. Because with mod_rewrite you can only rewrite a fixed amount of URL arguments at a time (here one with every rewrite). With PHP you can parse any arbitrary number of arguments like this:
$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$segments = explode('/', $_SERVER['REQUEST_URI_PATH']);
if (count($segments) > 2) {
for ($i=4, $n=count($segments); $i<$n; $i+=2) {
$_GET[rawurledecode($segments[$i-1])] = rawurldecode($segments[$i]);
}
$_GET['page'] = rawurldecode($segments[1]);
}
Then all you need for mod_rewrite is this single rule to rewrite the requests to your index.php:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !^/bsiadmin/index\.php$ /bsiadmin/index.php [L]