How to combine Apache redirects?

2019-07-11 03:51发布

问题:

I've got an Apache config that features multiple rewrite rules and redirects in order to get the cutest URLs, prevent duplicates for SEO, etc. Here's a snippet as an example (it features a lot more):

# Redirecting non-www to www 
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule (.*) http://www.example.com/$1 [R=301,L]

# Removing index.php
RewriteCond %{REQUEST_URI} index\.php$ [NC]
RewriteRule .* / [R=301,L]

# A big bunch of these
Redirect permanent /old-article.html  http://www.example.com/new-article.html
Redirect permanent /another-old-article.html  http://www.example.com/new-article2.html

This works well, but it happens to generate a lot of redirects. A common case looks like this:

http://example.com/index.php, 301 redirect to http://www.example.com/index.php
http://www.example.com/index.php, 301 redirect to http://www.example.com

It sometimes reaches 4-5 redirects.

Now, I want all these rules to be chained and generate only one 301 redirect, like this:

http://example.com/index.php, 301 redirect to http://www.example.com

I know I can spend an afternoon thinking and sorting the rules to a better match, and also that I can create combined rules. But that would complicate an already long file. I want a flag, operand or whatever that will execute all the rules as if they where internal and only issue the redirect once it has crawled every rule. Is this even possible?

回答1:

It seems as if simply re-ordering this would get you what you want:

# A big bunch of these
Redirect permanent /old-article.html  http://www.example.com/new-article.html
Redirect permanent /another-old-article.html  http://www.example.com/new-article2.html

# Removing index.php
RewriteRule ^/index.php http://www.example.com/ [R=301,L]

# Redirecting non-www to www 
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule (.*) http://www.example.com/$1 [R=301,L]

A direct request for an old article at the example.com domain:

http://example.com/old-article.html

Will result in a single redirect to:

http://www.example.com/new-article.html

A request for either http://example.com/index.php or http://www.example.com/index.php will result in a single redirect to:

http://www.example.com/

A request that doesn't match anything else will result in a single redirect from:

http://example.com/foo

To:

http://www.example.com/foo

This seems to cover all the bases. Have I missed anything?



回答2:

Remove the [L] flag from your RewriteRules, and they will be combined automatically.