3

I have the following in my htaccess file:

RewriteEngine On
RewriteBase /

# Check to see if the URL points to a valid file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# Trailing slash check
RewriteCond %{REQUEST_URI} !(.*)/$

# Add slash if missing & redirect
RewriteRule ^(.*)$ $1/ [L,R=301]

# Check to see if the URL points to a valid file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# Send to index.php for clean URLs
RewriteRule ^(.*)$ index.php?/$1 [L]

This does work. It hides index.php, and it adds a trailing slash... except when there is a query string.

This URL:

http://example.com/some-page

gets redirected to:

http://example.com/some-page/

but this URL:

http://example.com/some-page?some-var=foo&some-other-var=bar

does not get redirected. I would like for the above to be sent to:

http://example.com/some-page/?some-var=foo&some-other-var=bar

I've reached the limits of my understanding of redirects with this. If you have a working answer, I would really appreciate a walkthrough of what every line is doing and why it works. Double bonus awesomeness for an explanation of why what I have right now doesn't work when there is a query string involved.

jeremiahs
  • 3,985
  • 8
  • 25
  • 30

2 Answers2

3

Try adding a [QSA] to the end of the last Redirect rule to preserve the original query string as below

# Send to index.php for clean URLs, preserve original query string
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]

a walkthrough of what every line is doing and why it works.

See my comments below

#turn mod_rewrite engine on.
RewriteEngine On
#set the base for urls here to /
RewriteBase /

### if the is not a request for an existing file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

### and the URI does not end with a /
RewriteCond %{REQUEST_URI} !(.*)/$

### redirect and add the slash. 
RewriteRule ^(.*)$ $1/ [L,R=301]

### if the is not a request for an existing file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# rewrite to index.php passing the URI as a path, QSA will preserve the existing query string
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]
Ulrich Palha
  • 9,411
  • 3
  • 25
  • 31
  • I want to preserve the query string, not strip it. Your settings turn this: http:// example.com/some-page?test-var=foo to this: http:// example.com/some-page / I'm looking for this: http:// example.com/some-page/?test-var=foo – jeremiahs Feb 02 '12 at 19:45
1

I believe that if you change this:

RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ $1/ [L,R=301]

to this:

RewriteCond %{REQUEST_URI} !^([^?]*)/($|\?)
RewriteRule ^([^?]*) $1/ [L,R=301]

then it should do what you want.

The changes I made are:

  • In both rewrite-condition and -rule, I changed (.*) and ^(.*) to ^([^?]*), to ensure that, if there's a query-string, then it is not included in either regex. ([^…] means "any character that is not in ", so [^?] means "any character that is not a question mark".)
  • In the rewrite-condition, I changed $ to ($|\?), so as to match either end-of-URL or end-of-part-before-the-query-string.
  • In the rewrite-rule, I dropped the $, since it was no longer needed.
ruakh
  • 175,680
  • 26
  • 273
  • 307