Forum Moderators: phranque

Message Too Old, No Replies

Clean URLs for BOTH WordPress and Drupal?

Aksing how to set .htacess for mod_rewrite on Drupal and Wordpress

         

MikeSchinkel

8:31 pm on Jul 28, 2007 (gmt 0)

10+ Year Member



I've been trying to set up a plan vanilla website that will use both Drupal from the root and WordPress from the /blog/ directory. The two complexities are I'm trying to get the root domain to always redirect to the "www." equivalent and I'm trying to get URLs to always have a trailing slash on the path (i.e. /about/ instead of just /about) even when there are parameters (i.e. /about?foo=bar would be converted to /about/?foo=bar)

Try as I might, however, I can't get the mod_rewrite rules to correctly map clean URLs (fyi, for WordPress I want the simple /%postname%/ format). I think I've managed to get almost everything to work (though I'm not 100% sure) except I can't seem to get "/blog" to work (i.e. w/o the trailing slash.) It redirects to: //home/newclari/public_html/blog/

At the moment this is what I have:

#/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine on

RewriteRule ^/blog$ /blog/ [R=301,L]

#Ensure Trailing Slashes
RewriteCond %{REQUEST_FILENAME}!-f
RewriteCond %{REQUEST_FILENAME}!-d
RewriteCond %{REQUEST_URI} ^/[^\.]+[^/]$
RewriteRule ^(.*)$ [%{HTTP_HOST}...] [R=301,L]

#Ensure leading "www."
RewriteCond %{REQUEST_FILENAME}!-f
RewriteCond %{REQUEST_FILENAME}!-d
RewriteCond %{HTTP_HOST}!^www\.example\.net$ [NC]
RewriteRule .* http://www.example.net%{REQUEST_URI} [R=301,L]


# 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]

</IfModule>

#/blog/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine on

#Ensure Trailing Slashes
RewriteCond %{REQUEST_URI} ^/[^\.]+[^/]$
RewriteRule ^(.*)$ [%{HTTP_HOST}...] [R=301,L]

#Ensure leading "www."
RewriteCond %{HTTP_HOST}!^www\.example\.net$ [NC]
RewriteRule .* http://www.example.net%{REQUEST_URI} [R=301,L]

RewriteBase /blog/
RewriteCond %{REQUEST_FILENAME}!-f
RewriteCond %{REQUEST_FILENAME}!-d
RewriteRule . /blog/index.php [L]

</IfModule>

Thanks in advance for any help figuring out what I should be using and why.

Also, can I do all of this in the root .htaccess file or is it better to do in two different .htaccess files?

jdMorgan

9:11 pm on Jul 28, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



To simplify this problem, realize that your rules which have the !-f and !-d RewriteConds will not be applied if the requested URLs resolve to an existing file or directory. As such, I don't think you want or need those qualifiers on your domain and slash fix-up redirects.

The problem with the filepath being injected into the rewritten URL is a symptom of some common server configuration problem or possibly just buggy mod_rewrite behaviour. I've been seeing lots of threads here recently reporting the same thing and although we have some work-arounds, I haven't figured it out completely yet.

The works-arounds are --as you noted-- to put the rules in the top-level .htaccess file (with patterns and paths changed appropriately), and/or to use %{REQUEST_URI} instead of a back-reference to a "(.*)" RewriteRule pattern.

Another reason to put all the rules into the top-level .htaccess is to prevent internal rewrites from being "exposed" by later external redirects. That is, all external redirects must be applied first, and only then can you do an internal rewrite without have a redirect "expose" that internal rewrite to the client.

I won't show the <IfModule> stuff here, because I'd rather get an error if mod_rewrite isn't installed or working properly. I recommend using <IfModule> only if you know the module might not be present and you prefer a 'silent failure' for some reason in that case.

That said, I'd suggest the following, all in the top-level .htaccess:


RewriteEngine on
#
# If requested URI does NOT (contain any periods or end with a slash),
# externally redirect to canonical domain and add a trailing slash
RewriteCond %{REQUEST_URI} !(\.¦/$)
RewriteRule (.*) http://www.example.net/$1/ [R=301,L]
#
# Externally redirect requests for any non-canonical domain to the canonical domain
RewriteCond %{HTTP_HOST} !^www\.example\.net [NC]
RewriteRule (.*) http://www.example.net/$1 [R=301,L]
#
# If requested /blog URL does not resolve to an existing file or
# directory, internally rewrite requests to /blog.index.php
RewriteCond %{REQUEST_URI} !/blog/index\.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^blog/ /blog/index.php [L]
#
# Else if requested URL does not resolve to an existing file or directory,
# internally rewrite to index.php script with the URL-path in the query string
RewriteCond %{REQUEST_URI} !/index\.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.php?q=$1 [L]

Replace the broken pipe "¦" character above with a solid pipe before use; Posting on this forum modifies the pipe characters.

I should add that -d and -f checks are "expensive" processing-wise; I added two RewriteConds to avoid running them unnecessarily, but eliminate those filesystem checks completely if you can (For example, if /blog contains no subdirectories, then you can eliminate the !-d check in the /blog rewrite code).

Jim

MikeSchinkel

6:38 am on Jul 30, 2007 (gmt 0)

10+ Year Member



Wow Jim, thanks for the help and for the detailed explanations. Unfortunately since posting it I realized I had another problem with the querystrings, explained here: [webmasterworld.com...]