49

Suppose I have URLs with query string parameters like these:

/index.php?book=DesignPatterns&page=139
/index.php?book=Refactoring&page=285

Using mod_rewrite, how can I redirect them to SES URLs like these?

/DesignPatterns/139
/Refactoring/285
Patrick McElhaney
  • 57,901
  • 40
  • 134
  • 167

1 Answers1

109
RewriteCond %{QUERY_STRING} book=(\w+)&page=(\d+)  
RewriteRule ^index.php /%1/%2? [L,R=301]

Because RewriteRule only looks at the path (up to but not including the question mark), use RewriteCond to capture the values in the query string.

Note that the matches from RewriteCond are captured in %1, %2, etc., rather than $1, $2, etc.

Also note the ? at the end of RewriteRule. It tells mod_rewrite not to append the original query string to the new URL, so you end up with /DesignPatterns/151 intead of /DesignPatterns/151?book=DesignPatterns&page=151.

The [L,R=301] flags do two things:

  1. L ensures that no other rules that might otherwise match will be processed (in other words, it ensures this is the "last" rule processed).
  2. R=301 causes the server to send back a redirect response. Instead of rewriting, it tells the client to try again with the new URL. The =301 makes it a permanent redirect, so that, among other things, search engines will know to replace the old URL with the new URL in their indexes.
Patrick McElhaney
  • 57,901
  • 40
  • 134
  • 167
  • 1
    You probably also want the [L] flag when you have multiple rewrite rules. The [L] flag stops processing after the rule has matched, and the [R] flag DOES NOT implicitly include it. – TheJosh Jul 18 '13 at 04:07
  • 1
    The $ vs % were killing me. I had no idea. Thank you! – keithwyland Jan 21 '15 at 20:11
  • 7
    To not append the original query string to the new url use `[QSD]` flag (http://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_qsd) – Uzair Farooq Oct 05 '15 at 06:50
  • 1
    Answers like this make me wish I could star them for later easy finding. Instead I end up starring the question. – Luciano Jul 21 '16 at 11:17
  • @Luciano just recognize it by upvoting the answer on a question you starred. – ahnbizcad Aug 27 '16 at 18:38
  • 1
    isn't this invalid? you'd need to escape the dot in `^index.php` with `^index\.php` – ahnbizcad Aug 27 '16 at 18:38
  • 1
    I spend like 4 hours debugging :D until I googled and I discovered that mod rewrite doesn't match the query string – fpilee Jan 19 '18 at 01:33