Friendly Url .htaccess

2020-04-21 07:45发布

问题:

I have tried to follow the directions on .htaccess short and friendly url but am unable to achieve these results.

If I use the following it works fine:

RewriteEngine On
RewriteRule ^([^/]*)\.html$ /index.php?page=$1 [L]

However if I use:

RewriteEngine On
RewriteRule ^([^/]*)$ /index.php?page=$1 [L]

I receive an internal server error.

All I am trying to achieve is to be able to use http://website.com/about instead of http://website.com/about.html

回答1:

These rules:

RewriteEngine On
RewriteRule ^([^/]*)$ /index.php?page=$1 [L]

Is causing an internal rewrite loop. The rewrite engine loops through all of the rules until either the internal redirect limit has been reached (thus resulting in a 500 Server error) or the resulting URI coming out of the engine is the same one that went into it. Additionally (and this is a very important concept), the leading slash of the URI is removed before it is sent to the rewrite engine for rules in an htaccess file. So here we have:

  1. Request is made: http://domain.com/blah
  2. URI = /blah
  3. strip leading slash, URI = blah
  4. blah matches ^([^/]*)$, rule is applied, URI = /index.php?page=blah
  5. blah not equal /index.php
  6. rules loop, URI = /index.php
  7. strip leading slash, URI = index.php
  8. index.php matches ^([^/]*)$, rule is applied, URI = /index.php?page=index.php
  9. index not equal /index.php
  10. rules loop, URI = /index.php
  11. strip leading slash, URI = index.php
  12. index.php matches ^([^/]*)$, rule is applied, URI = /index.php?page=index.php
  13. index not equal /index.php

etc.

You have a couple of choices in how to deal with this. The simples would be to simply remove the / from your target:

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

This would make it so in step 9 above, the index would equal index.php, thus stopping the rewrite process (before it gets applied the second time). The only downside with this is if you need to redirect, or if the htaccess file gets moved, the relative URI in the target can sometimes be mistaken for a file-path instead of a URL-path (apache guesses this, and sometimes apache guesses wrong). This can be fixed by including a base:

RewriteBase /
RewriteRule ^([^/]*)$ index.php?page=$1 [L]

You could also add conditions to make it so URL's that point to an existing resource will exclude this rule from getting applied:

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

So if the URI points to an existing file or directory, the rule is skipped. So after the first rewrite when the URI becomes /index.php, since that file exists, the rule is skipped the 2nd time around. This also makes it so requests for images, css, scripts or static pages in your document root won't get routed through index.php. If this isn't what you want, you can also flat-out skip if the URI is already an index.php:

RewriteCond %{REQUEST_URI} !^/index.php
RewriteRule ^([^/]*)$ /index.php?page=$1 [L]