mod_rewrite newbie - is this correct? - mod-rewrite

This is supposed to take any uri and send it as part of a query string to a script that will handle it.
RewriteEngine On
RewriteCond %{REQUEST_URI} !(css.php|gif|jpe?g|png|css|js|json|xml|ico)$
RewriteRule ^(.*)(/)?$ index.php?where=$1 [QSA,L]
I'm asking because it works on some servers and not on others. On some it just disregards the whole thing as if url rewriting is off, and on others it reports a bad request whenever .htaccess with the above content is uploaded.

BTH I would change this rule a bit:
RewriteEngine On
RewriteCond %{REQUEST_URI} !\.(css.php|gif|jpe?g|png|css|js|json|xml|ico)$
RewriteRule ^(.*)/?$ index.php?where=$1 [QSA,L]
Added \. into RewriteCond pattern to ensure that it only works for files with such EXTENSIONS (otherwise pattern will also match files that have that text at the end i.e. /something/mygif <> /something/my.gif).
Replaced (/) by / in RewriteRule pattern -- it makes no difference in functionality but a bit lighter on resources.
Back to main topic:
If it "disregards the whole thing as if url rewriting is off" then most likely .htaccess files are not supported/enabled (or it should have different name as configured by AccessFileName directive: e.g. AccessFileName ht.access).
To check it try placing some other directives into .htaccess and see if it works (like: ErrorDocument 404 /404.php or DirectoryIndex index.php etc).
If it "reports a bad request whenever .htaccess with the above content is uploaded" then most likely these directives are not allowed to be placed in .htaccess (requires AllowOverride All or at least AllowOverride FileInfo; see docs) or mod_rewrite is not enabled.
Check Apache's error log -- it should have entries mentioning this moment.

Related

Yii :: Issue Using Showscriptname = False And Url Manager

I am currently having an issue using the URL manager and/or the apache mod_rewrite or maybe something else entirely.
With showScriptName set to false, navigating to addresses such as domain.com/login, domain.com/logout, domain.com/site/login are all behaving the same way. It simply shows the main site/index, as if I were to navigate to domain.com/eeofjew9j8jfdedfmewf (jibberish).
Maybe it's an issue with my Yii settings? Here are those (sorry for the sloppiness):
'components'=>array(
'urlManager'=>array(
'urlFormat'=>'path',
'showScriptName'=>false,
'rules'=>array(
'<controller:\w+>/<id:\d+>'=>'<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
'login'=>'site/login',
'logout'=>'site/logout',
'register'=>'users/register'
),
,...
Here is how I have my .htaccess setup in the www root:
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
I am using a VPS server, so I have root access to make any changes needed to apache. I've checked my phpinfo and mod_rewrite is running and enabled. In my apache config, I have for my www directory:
AllowOverride All
Options Indexes FollowSymLinks MultiViews
Order allow,deny
Allow from all
I've been scratching my head on this issue through 3 different hosts (godaddy, dreamhost, and lithiumhosting) so I'm assuming it's an issue on my end with this. Now that I have a VPS though, I'm hoping I can finally figure out my issue and solve it.
First verify that the server is parsing the .htaccess file. This is simply done by placing random text in the .htaccess file such as
CREATE AN ERROR
If this gives you a server error then the file is being parsed. You may have to move the .htaccess file up a directory to get this to work.
After this is working check to make sure the rewrite module in Apache is on. First check phpinfo and look for the running module. If not you may have to delete the comment (#) character in front of the module.
After the module shows up in phpinfo then see if you can do a basic rewrite to make sure that there are not problems with Apache.
RewriteEngine on
RewriteRule ^ http://google.com/? [L,R]
If that is not working try adding the
Options +SymLinksIfOwnerMatch
to the file
Once you have Apache doing it's part now it is up to yii. This code:
RewriteEngine On
RewriteBase /mybasedirectory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)\?*$ index.php/$1 [L,QSA]
adds the rewrite base option which may be necessary if you do not have the files in the document root such as htdocs
finally if that does not solve the problem then limit your rule to a simple rule such as
'contact'=>'site/contact',
and see if at least redirects to where you think it should. Of course you may have to check the basic rules of .htaccess again to make sure that overide is allowed and there isn't an errant .htaccess in a subdirectory. I hope that helps. I finally got mine working.
What happens if you delete these lines!
enter code here
# otherwise forward it to index.php
RewriteRule . index.php
if you add this code see if it works
'<action:(login|logout|register|contact)>' => 'site/<action>',

Rewriting behaves differently in .htaccess vs vhost

I'm using following chunk of instructions to rewrite www to non www url:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,NC,L]
</IfModule>
If I place it in .htaccess file, it works fine.
If I place it in vhost file, after rewriting two forward slashes are added to the host, for example www.domain.com will become domain.com//
Am I missing something?
Also, is it worth placing all .htaccess content in vhost performancewise?
RewriteRule is behaving as the docs say.
There is a difference in what RewriteRule matches against when in VirtualHost context & Directory & .htaccess context.
From RewriteRule Directive Apache Docs
What is matched?
In VirtualHost context, The Pattern will initially be matched against the part of the URL after the hostname and port, and before the query string (e.g. "/app1/index.html").
In Directory and htaccess context, the Pattern will initially be matched against the filesystem path, after removing the prefix that lead the server to the current RewriteRule (e.g. "app1/index.html" or "index.html" depending on where the directives are defined).
If you wish to match against the hostname, port, or query string, use a RewriteCond with the %{HTTP_HOST}, %{SERVER_PORT}, or %{QUERY_STRING} variables respectively.
So, when in VirtualHost the server in not in a directory context so prefix / will not be removed. Also remember when matching with RewriteRule in VirtualHost context, the pattern will always begin with /.
So, your RewriteRule Should be:
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^/(.*)$ http://%1/$1 [R=301,NC,L]
in VirtualHost context.
Also, is it worth placing all .htaccess content in vhost performancewise?
Yes, Definitely. One reason is that, no file (.htaccess) will be read every time you are accessing a page.

Rewrite Rule(s) for domain aliases

Situation: I have a single (main) domain, which has several aliased domains, each of which are pointing at the same Plesk-based server (for instance, I have example.com as main, with something.net, anotherone.co.uk, and several others all as aliases of the main domain account). This means that whenever I enter the domain name into my address bar of any of the aliases, it goes directly to the account of the main domain (example.com).
Problem: Based on the domain name of the alias(es), I have an index.php that redirects each domain differently (for instance, requests to domain A redirects to a corporate site, domain b goes to a thanks site etc.) Which works great, but if a directory is added after the domain URL (i.e. somealias.com/something) then it gives a 404 not found error.
What I would really appreciate, if someone can help me out, is a (single if possible) rewrite ruleset that would essentially strip off ALL trailing directories and/or GET requests, and only leave the typed-in base URL, so then the php script sitting in the main domain document root can take over and deal with the request appropriately.
Strangely enough, I've not been able to find a (simple) solution for this anywhere. Is it a case of having to define a rule for each of the aliased domains individually?
Try the following,
#Options +FollowSymLinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www.olddomain.com$[OR]
RewriteCond %{HTTP_HOST} ^olddomain.com$
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=301,L]
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !=/
RewriteCond %{REQUEST_URI} !=/index.php
RewriteRule .* http://%{HTTP_HOST}/? [L]
This will take ALL requests except root folder / (e.g. http://example.com/) or index file (e.g. http://example.com/index.php) and redirect them to the root folder (e.g. http://example.com/some-url will be redirected to http://example.com/).
You may need to replace index.php by the file that is get executed when you hit the root folder (Apache will silently rewrite http://example.com/ to http://example.com/index.php (depending on your actual settings) as it needs to have a file to execute otherwise it may show an error).
Alternatively (possibly even better -- depends on your actual setup and requirements) you may use these rules -- this will redirect only non-existing URLs. So if you have an image meow.png on your site, these rules will allow you to access it (http://example.com/meow.png):
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* http://%{HTTP_HOST}/? [L]
UPDATE:
If you going to place this into config file (httpd-vhost.conf or httpd.conf) then use these rules:
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteCond %{REQUEST_URI} !=/index.php
RewriteRule .* http://%{HTTP_HOST}/? [L]
It seems to me that all the sites are hosted on the same server (probably using the same code base).
If your index.php is a front controller you can redirect everything to your index.php and decide in the first lines of index.php what front controller to load (like backend.php).
If you don't mind having to maintain a list of the aliases you can define a hash of [alias] => path-to-front-controller.
In the front controller of you main domain you check the alias name (using $_SERVER['SERVER_NAME'] for example) against the hash and load the appropriate file.
You will have to add and entry to the hash each time you add anew alias. If they are not generated dynamically maintaining this hash is not a lot of hassle.

Renaming PHP URLs with HTACCESS

I am building a web app that puts out a link like the following:
http://www.sample.com/?a=bj7phm
I would like for it to look something like this:
http://www.sample.com/BJ7PHM
Is this possible within the HTACCESS?
-B
In order to do URL rewriting, you first need to:
Make sure you have mod_rewrite enabled on your server.
Make sure you have the proper permissions to add rules to your .htaccess file.
(AllowOverride must be set to All or include FileInfo)
Then create the following .htaccess file in your web root:
RewriteEngine On
RewriteRule ^([\-_0-9A-Za-z]+)$ index.php?a=$1 [L]
You can customize RewriteRule as much as you want.
The first parameter is the regular expression to match the REQUEST_URI with (relative to the folder the .htaccess is in).
The second parameter is what you want to rewrite it to, $n being your match groups.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^([0-9a-zA-Z+]{1,7})$?a=$1 [L]
</IfModule>

How to reference the current directory from .htaccess using mod_rewrite?

I'd like to use mod_rewrite to make pretty URLs, but have a single version of the .htaccess file that can be used for any user on a server.
So far I have the standard pretty URL .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
Ideally, I would like something similar to
RewriteRule ^(.*)$ %{URL of this file's directory}/index.php/$1 [L]
This documentation would lead me to believe that what I want is not necessary:
Note: Pattern matching in per-directory context
Never forget that Pattern is applied to a complete URL in per-server configuration files. However, in per-directory configuration files, the per-directory prefix (which always is the same for a specific directory) is automatically removed for the pattern matching and automatically added after the substitution has been done. This feature is essential for many sorts of rewriting - without this, you would always have to match the parent directory which is not always possible.
I still get the wrong result, though, whether or not I put a leading / in front of the index.php on the RewriteRule.
This,
http://server/test/stream/stream
turns into
http://server/index.php/stream
not
http://server/test/index.php/stream
when the .htaccess file is in /test/.
I was having a similar problem, but found that simply leaving off the root '/' resulted in my test web server (xampp on windows) serving a URL similar to:
http://localhost/C:/xampp/htdocs/sites/test/
Not perfect. My solution is to use a RewriteCond to extract the path from REQUEST_URI. Here's an example for removing the unwanted "index.php"s from the end of the URL:
RewriteCond %{REQUEST_URI} ^(.*)/index.php$
RewriteRule index.php %1/ [r=301,L]
Note: the percent sign in "%1/", rather than a dollar sign.
%1-%9 gets the patterns from the last matched RewriteCond, $1-$9 gets the patterns from the RewriteRule.
See:
http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#rewritecond
Cheers :)
Turns out that it does matter whether I put a leading / in front of index.php or not. By leaving it off, the script works correctly. I had been testing with the R flag which was using physical directories on the redirect.

Resources