Config: Windows 2000 server, Apache 2.0.50, mysql 4.0.20, php 4.3.8

I'd like to use clean URLs, and put the .htaccess parameters in the Apache config file (httpd.conf) instead of using the .htaccess file. This is not a problem as I have full access to the httpd.conf file.

Questions:

1) one of the reasons for doing this is my understanding that using httpd.conf instead of .htaccess is better performance-wise. Can anybody confirm that this is correct ?

2) I tried to copy the content of the .htaccess file into the part of the httpd.conf file. However enabling clean URLs in the Drupal admin page does not work. I have seen a number of posts relating to problems with enabling clean URLs, but they all seem to relate to setups where .htaccess is used. I am wondering if the parameters should be put differently if httpd.conf is used. Would anybody who has done it this way be in a position to help ?

Thanks !

Comments

chx’s picture

Hi!

Apache does a stat for .htaccess in every subdirectory from its webroot until it arrives to the directory where the file to be served lies. If it finds a .htaccess, it reads -- here is the minor perfomance hit, really minor, one file read and most probably from memory, 'cos it's small and frequently used.

I suppose you've enabled the rewrite module -- and what about AllowOverwrite? you need AllowOverride File at least.

--
Drupal development: making the world better, one patch at a time. | A bedroom without a teddy is like a face without a smile.

yuit’s picture

Thanks for your reply. From reading http://httpd.apache.org/docs-2.0/mod/core.html#allowoverride , I got the understanding that AllowOverride only related to directives found in .htaccess , and was irrelevant when it comes to parameters that feature in the httpd.conf file. As I was planning NOT to use .htaccess, I have not set AllowOverride to 'All'. Is my thinking wrong ?

yuit’s picture

I have now found the solution to my problem. Let me report it here in case anyone in a similar situation needs some hints:

1) one of the differences between mod_rewrite rules put in httpd.conf and .htaccess is the need to add a '/' when using httpd.conf. I must have been blind as this is well documented at http://httpd.apache.org/docs-2.0/mod/mod_rewrite.html#rewriterule

Therefore :
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
becomes
RewriteRule ^/(.*)$ /index.php?q=$1 [L,QSA]
in my case

2) RewriteCond lines need to be added to exclude from the rewrite rules any subdirectory to which you need to preserve access, such as 'themes' and 'misc'

3) When connecting to the homepage of my Drupal site, I could see the page layout, but was getting a "page not found" text where the content should have been. It appears that '[OR]' needs to be added at the end of < RewriteCond %{REQUEST_FILENAME} !-f > to solve this issue.

All in all, the code looks like this in the end in my httpd.conf file :

RewriteCond %{REQUEST_URI} !^/misc/
RewriteCond %{REQUEST_URI} !^/themes/
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(.*)$ /index.php?q=$1 [L,QSA]

I am now the happy user of a Drupal install which does not need an .htaccess file and does not have to bother about AllowOverride directives :-)

dongrocker’s picture

wow, yuit, thanks for posting this; it could be really useful (if I develop the nerve to try it...)

fwnetwork’s picture

Thank you for the instructions. They are excellent.

Would you know if anything need to be done with the rest of the .htaccess content?
Should I transfer it to the httpd.conf file?
Where should I place it and is there any restrictions?

Thank you again

yuit’s picture

Since my last post, I have moved to Drupal 4.6.3 (setup is : Apache 2.0.54 , php 4.4.0).

I also put the rest of .htaccess into httpd.conf , into the directive for the drupal site concerned. It works fine for me.

chx’s picture

I would take those lines with a huge grain of salt. httpd.conf and .htaccess have the exact same syntax for mod_rewrite!

RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d

Why the OR? I presume that because of the OR you needed to add the other two RewriteCond lines.

And why did you change the RewriteRule? This totally confuses me, it's really unnecessary. Yes, I am aware that sometimes an

RewriteRule ^(.*)$ /index.php?q=$1 [L,QSA]

is needed, but so far I needed this only in the presence of mass vhost alias module.

--
Drupal development: making the world better, one patch at a time. | A bedroom without a teddy is like a face without a smile.

yuit’s picture

Thanks for your reply (and apologies for the much delayed reply :-) )

Since my last post, I have moved to Drupal 4.6.3, Apache 2.0.54 and php 4.4.0. Remember that what I described was (is) a working configuration for me after quite a few try-and-fail attempts at modifying the parameters one by one. I am not a ModRewrite expert, and have come to agree with all the comments read that it is a tricky beast. Any expert advise would much appreciated on errors I may have made.

Also to be noted: I have several Drupal sites configured as <VirtualHosts> in httpd.conf, and I use the multi-site feature of Drupal 4.6 (single install of the Drupal files + use of dedicated subdirectories for config files in the "sites" directory)

Here is a summary of my step-by-step approach to end up with httpd.conf working without the need for .htaccess :

1) using the same syntax as in .htaccess :

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

Result: Apache2 sends back a "bad request" error message. No content displays on screen.

2) adding '/' to the RewriteRule line :

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(.*)$ /index.php?q=$1 [L,QSA]

Result:
a) the homepage of the Drupal site displays on screen, but no template is applied. A look at the Drupal error log shows a "page not found" error for favicon.ico , themes/bluemarine/logo.png , themes/bluemarine/style.css and misc/drupal.css. It therefore looks like the RewriteCond do not work properly. It may be due to the use of a VirtualHost and multi-site Drupal install. I do not know.
b) A few stories had been created to populate the homepage with news ("Default Front Page" parameter set to "node" in the ADMINISTER => SETTINGS menu). However I get a "page not found" error message and none of the stories displays despite the fact that the "anonymous user" has "access content" rights. A look at the Drupal error log shows a "page not found" error for index.php. Interesting...

3) Adding [OR] at the end of the first RewriteCond line :

RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(.*)$ /index.php?q=$1 [L,QSA]

Result:
a) the template is still not applied. Same as in 2.a above
b) The homepage now correctly displays the stories and I no longer get a "page not found" error for index.php

4) Adding specific RewriteCond lines for the 'misc' and 'themes' directories :

RewriteCond %{REQUEST_FILENAME} !^/misc
RewriteCond %{REQUEST_FILENAME} !^/themes
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(.*)$ /index.php?q=$1 [L,QSA]

Result: it now works !
Notes:
* [OR] is not needed apparently for the RewriteCond lines for 'misc' and 'themes'
* if I remove [OR] from the third RewriteCond line, I get a "page not found" error for index.php again.

Here is what my httpd.conf file looks like in the end for the concerned Drupal site:

<VirtualHost *:80>
# Protect files and directories from prying eyes.
<Files ~ "(\.(inc|module|pl|sh|sql|theme|engine|xtmpl)|Entries|Repositories|Root|scripts|updates)$">
  Order deny,allow
  Deny from all
</Files>

# Set some options.
Options -Indexes
Options +FollowSymLinks

# Customized error messages.
ErrorDocument 404 /index.php

# Set the default handler.
DirectoryIndex index.php

# Override PHP settings in Apache 2 (Apache 1.3 code removed as it is irrelevant here).
<IfModule sapi_apache2.c>
  php_value magic_quotes_gpc                0
  php_value register_globals                0
  php_value session.auto_start              0
</IfModule>

# Reduce the time dynamically generated pages are cache-able.
<IfModule mod_expires.c>
  ExpiresByType text/html A1
</IfModule>

# Various rewrite rules (old-style Cond/Rules removed as they are unnecessary in my setup)
<IfModule mod_rewrite.c>
  RewriteEngine on

  # Rewrite current-style URLs of the form 'index.php?q=x'.
  RewriteCond %{REQUEST_FILENAME} !^/misc
  RewriteCond %{REQUEST_FILENAME} !^/themes
  RewriteCond %{REQUEST_FILENAME} !-d [OR]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^/(.*)$ /index.php?q=$1 [L,QSA]
</IfModule>

    ServerAdmin webmaster@mysite.com
    DocumentRoot c:/wwwroot/drupal_46
    ServerName www.mysite.com
    ErrorLog c:/wwwlogs/error_log
    CustomLog c:/wwwlogs/access_log combined
</VirtualHost>

Feedback from ModRewrite experts would be much welcome if there is an easier way to do things, or if I have made obvious mistakes. You should be careful and only re-use what I have described above with caution. There may be other issues (security or else) introduced by the above code.

Marco Palmero’s picture

Thanks yuit...

after reading and searching all that you need to do to allow clean URLs is to put in this code

RewriteCond %{REQUEST_FILENAME} !^/misc
RewriteCond %{REQUEST_FILENAME} !^/themes
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(.*)$ /index.php?q=$1 [L,QSA]

All the clean URLs are now working properly...

What I did was I transported my website to my localhost (laptop)... now there is a brand new error coming up... its related to the image_assist.module

warning: getimagesize(images/DSC_7026.JPG) [function.getimagesize]: failed to open stream: No such file or directory in C:\webdev\xampp\htdocs\blog\modules\img_assist\img_assist.module on line 550.
warning: getimagesize(images/DSC_7026.JPG) [function.getimagesize]: failed to open stream: No such file or directory in C:\webdev\xampp\htdocs\blog\modules\img_assist\img_assist.module on line 525.

I wonder how to fix this error?

---------------------------------------------------------
My Blog - Photography, travelling and University...

yuit’s picture

Yes, I was having similar problems which were requiring a specific 'RewriteCond' line for the directory of each module concerned by such an error.

However look at the next comment below for a better way to do the whole thing.

mikispeed’s picture

Many thanks, this solved my problem.
Best regards!

yuit’s picture

Config: Windows 2000 server, Apache 2.0.55, mysql 4.0.26, php 4.4.0

I have just updated from Drupal 4.5.5 to 4.6.3 and took this opportunity to look again at the issue. A very useful post on his blog by Scott Laird (see http://scottstuff.net/blog/articles/2004/05/21/more-drupal) gave the answer to simplifying the set of parameters I indicated before.

Apparently it all comes down to the fact that the DocumentRoot needs to be added as a prefix in the RewriteCond lines when running Apache2.

Therefore, instead of :

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f

One should write (on Windows; change the path to where your Drupal install directory is):

RewriteCond c:/htdocs/drupaldir/%{REQUEST_FILENAME} !-f
RewriteCond c:/htdocs/drupaldir/%{REQUEST_FILENAME} !-d

or (on Unix; change the path to where your Drupal install directory is):

RewriteCond /var/www/drupaldir/%{REQUEST_FILENAME} !-f
RewriteCond /var/www/drupaldir/%{REQUEST_FILENAME} !-d

Once this is done, there is no longer any need to add RewriteCond lines such as:

RewriteCond %{REQUEST_FILENAME} !^/misc
RewriteCond %{REQUEST_FILENAME} !^/themes

[OR] is no longer needed after :
RewriteCond %{REQUEST_FILENAME} !-f

We then need to put a / in the RewriteRule line before index.php. But contrary to what was working in my setup before, a / is no longer needed before (.*)$.

This last line now reads:
RewriteRule ^(.*)$ /index.php?q=$1 [L,QSA]

To summarize, Here is what my httpd.conf file looks like for my Drupal site after having updated it to 4.6.3 and with the above changes:

# Protect files and directories from prying eyes.
<Files ~ "(\.(inc|module|pl|sh|sql|theme|engine|xtmpl)|Entries|Repositories|Root|scripts|updates)$">
  Order deny,allow
  Deny from all
</Files>

# Set some options.
Options -Indexes
Options +FollowSymLinks

# Customized error messages.
ErrorDocument 404 /index.php

# Override PHP settings in Apache 2 (Apache 1.3 code removed as it is irrelevant here).
# More exist in sites/default/settings.php, but the following cannot be changed at runtime.

<IfModule sapi_apache2.c>
  php_value magic_quotes_gpc                0
  php_value register_globals                0
  php_value session.auto_start              0
</IfModule>

# Reduce the time dynamically generated pages are cache-able.
<IfModule mod_expires.c>
  ExpiresByType text/html A1
</IfModule>

# Various rewrite rules.
<IfModule mod_rewrite.c>
  RewriteEngine on
  # Rewrite current-style URLs of the form 'index.php?q=x'.
  RewriteCond c:/htdocs/drupaldir/%{REQUEST_FILENAME} !-f
  RewriteCond c:/htdocs/drupaldir/%{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ /index.php?q=$1 [L,QSA]
</IfModule>

Steve Ratcliffe’s picture

What I did is place all the rewrite statements inside a <Directory> section. In your example that would be:

<Directory c:/htdocs/drupaldir>
     RewriteEngine on
     # Rewrite current-style URLs of the form 'index.php?q=x'.
     RewriteCond %{REQUEST_FILENAME} !-f
     RewriteCond %{REQUEST_FILENAME} !-d
     RewriteRule ^(.*)$  index.php?q=$1 [L,QSA]
</Directory>

I then found no need to change the actual re-write lines at all. (I use linux so apologies if the directory statement is not quite right for Windows).

TessaC’s picture

After struggling with this for a while, trying the other stuff in this thread, this approach solved my problem.

I am using windows and my directory statement looks exactly like yours.

I have a question though: what does your RewriteBase look like? And what is your base_url in settings.php? I'm somewhat confused about which is used when. I'll go look some more for how the rewriting works but thought I'd ask what your config looks like.

I have
httpd.conf

<Directory "f:/htdocs/drupal">
...
RewriteBase /drupal
...
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

settings.php
$base_url = 'http://<i>www.my_web_site.com</i>/drupal';

Thanks for any feedback.

drewish’s picture

This is the correct way to do it.

audihertz’s picture

After many headaches and trials, I got this to work for me as well. Going in through Unix, I edited the httpd.conf file for the virtual host (/etc/httpd/sites) and it worked like a peach!

Sample of what I did:

<IfModule mod_rewrite.c>
        <Directory "/htdocs/www/drupal">
                RewriteEngine on
                # Rewrite current-style URLs of the form 'index.php?q=x'.
                RewriteCond %{REQUEST_FILENAME} !-f
                RewriteCond %{REQUEST_FILENAME} !-d
                RewriteRule ^(.*)$  index.php?q=$1 [L,QSA]
        </Directory>
</IfModule>

Thanks for this tip!!

grakhul’s picture

The above worked for me with no modification. Simply PUT this in your httpd.conf and restart the apache server:

<Directory /var/to/my/web/directory/>
     RewriteEngine on
     # Rewrite current-style URLs of the form 'index.php?q=x'.
     RewriteCond %{REQUEST_FILENAME} !-f
     RewriteCond %{REQUEST_FILENAME} !-d
     RewriteRule ^(.*)$  index.php?q=$1 [L,QSA]
</Directory>
RobRoy’s picture

Just ran across this in a non-standard Apache configuration. After getting the 400 Bad Request I looked at http://drupal.org/node/43788 and did two things:

1. Changed my rewrite rules in httpd.conf VirtualHost directive to this.

 
  # Rewrite current-style URLs of the form 'index.php?q=x'.
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ /index.php?q=$1 [L,QSA]

2. Uncommented and specified $base_url in settings.php.

Voila!

--
Rob
Founder and Director
Electronic Insight Corporation

Recent Drupal Projects: MP3PIG | MySpace Layouts

--
Rob Barreca
Drupal Architect
ChipIn, Inc.
Electronic Insight Corporation

Learn how you can contribute to Drupal.

nath’s picture

I had some problems with most pages not finding stylesheets and images. Setting $base_url fixed this for me.

müzso’s picture

I've figured out the problem with $base_url. It's related to an Apache weirdness. Drupal uses the SCRIPT_NAME server variable for calculating $base_url if it's not specified in settings.php. However Apache (or mod_rewrite?) sets SCRIPT_NAME differently if you use the htaccess method and if you use the core Apache config (eg. /etc/apache2/httpd.conf).

If you use a .htaccess file and have the proper URL-rewriting rules enabled and call an URI that is rewritten by mod_rewrite (eg. /node/34/edit), then SCRIPT_NAME will be changed to to "/index.php". Check out the conf_init() function in includes/bootstrap.inc ... here you'll find the code that calculates $base_url. The code assumes that SCRIPT_NAME points to index.php and thus takes the path before the last non-directory component in SCRIPT_NAME to be the directory prefix of your Drupal setup and uses that to set $base_url.

However if you put the rewriting rules into you virtualhost config, then SCRIPT_NAME is not changed! It stays the original URI, eg. /node/34/edit. Now conf_init() assumes that this points to index.php, thus removes the last component and ends up with /node/34/ as the directory used for $base_url (so if your hostname is example.com, then $base_url will be "http://example.com/node/34/"). And all absolute URLs generated by your Drupal setup will have this $base_url prefix ... thus your page will break (CSS files will not be found, etc.).

If you put the rewrite rules in your virtualhost config, but inside the proper <Directory> container, then it'll behave just the same as if you used a .htaccess file ... thus SCRIPT_NAME will point to index.php and conf_init() will work correctly even if no $base_url is defined in settings.php.

najibx’s picture

I put inside the proper container of respective virtualhost config, it does not behave with similar .htaccess file.
When I delete my .htaccess. Not work. But put back, it works. I have to put in the /usr/local/apache/conf/httpd.conf but under the respective virtualhost, as it seems that cpanel generate this automatically in this main file but under different virtualhost config.

I would not want to set $base_url in settings.php since I would like use to Domain Module.

<VirtualHost xxx.xxx.xxx.xxx:80>
<Directory /home/xxx/public_html/drupal>
  RewriteEngine on
  AllowOverride All
  RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
  RewriteRule ^(.*)$ http://example.com/$1 [L,R=301]
  RewriteBase /
  # Rewrite URLs of the form 'x' to the form 'index.php?q=x'.
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
</Directory>
...
...
...
... bunches of other stuff
</VirtualHost>

Any ideas.

najibx’s picture

I put it in a wrong virtualhost config domain. It works, if put correctly but :

1. It's really a hassle that I have to this on each virtualhost config domain. How can I have a generic one?
2. I can't move back and forth to Disabled or Enabled Clean URLs. Once disabled, I can enabled back. (only via PHPmyadmin) clean_url in variable table

amxcld9’s picture

OK so Mod_rewrite is enables, when I run apachectl -M
at the command prompt I see: rewrite_module (static)

But when I install Drupal (6.20) it complains that it is NOT enabled?

This is on Hostgator VPS. And have root access and I want to use the recommended httpd.conf method.

Any ideas where I go from here?
------------------------------------------

My reasoning for wanting to do this the right way is due to the following
Quote from: http://drupal.org/getting-started/clean-urls

"There are two ways to prepare your server for clean URLs to work in Drupal. If you have complete control of your server, for example because you run your own server, are installing a development site on your personal computer, or have a dedicated server hosting account, then you should enable clean URLs in the httpd.conf file for better performance and security. However, if you have a shared hosting account (at DreamHost, BlueHost, HostGator, GoDaddy, 1and1, et al.), you will not be able to modify the httpd.conf file and should use the Drupal .htaccess file instead."