Apache 参考:mod_rewrite、URL rewriting和";“漂亮链接”;解释
“漂亮链接”是一个经常被要求的话题,但很少有人对它进行充分的解释。是制作“漂亮链接”的一种方法,但它很复杂,语法非常简洁,很难理解,并且文档假定对HTTP有一定的熟练程度。有人能简单地解释一下“漂亮链接”是如何工作的,以及如何使用mod_rewrite来创建它们吗Apache 参考:mod_rewrite、URL rewriting和";“漂亮链接”;解释,apache,.htaccess,mod-rewrite,friendly-url,regex,Apache,.htaccess,Mod Rewrite,Friendly Url,Regex,“漂亮链接”是一个经常被要求的话题,但很少有人对它进行充分的解释。是制作“漂亮链接”的一种方法,但它很复杂,语法非常简洁,很难理解,并且文档假定对HTTP有一定的熟练程度。有人能简单地解释一下“漂亮链接”是如何工作的,以及如何使用mod_rewrite来创建它们吗 其他常用名称、别名、干净URL的术语:URL、用户友好URL、-友好URL和MVC URL(可能用词不当)要了解mod_rewrite是什么,首先需要了解web服务器是如何工作的。web服务器响应。最基本级别的HTTP请求如下所示:
其他常用名称、别名、干净URL的术语:URL、用户友好URL、-友好URL和MVC URL(可能用词不当)要了解mod_rewrite是什么,首先需要了解web服务器是如何工作的。web服务器响应。最基本级别的HTTP请求如下所示:
GET /foo/bar.html HTTP/1.1
GET /foo/bar?baz=42 HTTP/1.1
RewriteRule ^/myblog/(*.)$ /blog/$1 [R=301,QSA,L]
RewriteRule my-blog/entry.php?id=(\d+) my-blog/$1--i-found-the-answer [R]
这是一个浏览器向web服务器发出的简单请求,请求其提供URL/foo/bar.html
。需要强调的是,它不请求文件,它只请求一些任意的URL。请求也可能如下所示:
GET /foo/bar.html HTTP/1.1
GET /foo/bar?baz=42 HTTP/1.1
RewriteRule ^/myblog/(*.)$ /blog/$1 [R=301,QSA,L]
RewriteRule my-blog/entry.php?id=(\d+) my-blog/$1--i-found-the-answer [R]
这和URL请求一样有效,更明显的是,它与文件无关
web服务器是一个侦听端口的应用程序,它接受来自该端口的HTTP请求并返回响应。web服务器完全可以自由地以其认为合适的任何方式响应任何请求/以您配置的任何方式响应。这个响应不是一个文件,它是一个HTTP响应,它可能与任何磁盘上的物理文件有关,也可能与之无关。web服务器不必是Apache,还有许多其他web服务器都是持久运行的程序,连接到响应HTTP请求的端口。你可以自己写一本。这一段的目的是让你不再认为URL直接等于文件,这一点理解起来非常重要。:)
大多数web服务器的默认配置是查找与硬盘上的URL匹配的文件。如果服务器的文档根设置为,比如说,/var/www
,它可能会查看文件/var/www/foo/bar.html
是否存在,如果存在,则为其提供服务。如果文件以“.php”结尾,它将调用php解释器,然后返回结果。所有这些关联都是完全可配置的;一个文件不必以“.php”结尾,web服务器就可以通过php解释器运行它,URL也不必匹配磁盘上的任何特定文件
mod_rewrite是重写内部请求处理的一种方法。当web服务器收到URL/foo/bar
请求时,您可以在web服务器查找磁盘上与之匹配的文件之前将该URL重写为其他内容。简单的例子:
RewriteEngine On
RewriteRule /foo/bar /foo/baz
此规则表示,只要请求与“/foo/bar”匹配,就将其重写为“/foo/baz”。然后,该请求将被处理为已被请求的/foo/baz
。这可以用于各种效果,例如:
RewriteRule (.*) $1.html
此规则匹配任何内容(*
)并捕获它((…)
),然后将其重写为追加“.html”。换句话说,如果/foo/bar
是请求的URL,那么它将被当作请求了/foo/bar.html
一样处理。有关正则表达式匹配、捕获和替换的详细信息,请参阅
另一个经常遇到的规则是:
RewriteRule (.*) index.php?url=$1
这同样会匹配任何内容并将其重写为index.php文件,原始请求的URL追加到URL
query参数中。也就是说,对于任何和所有传入的请求,都会执行index.php文件,该文件将有权访问$\u GET['url']
中的原始请求,因此它可以用它做任何事情
主要是将这些重写规则放入web服务器配置文件中。Apache还允许*您将它们放入文档根目录中名为.htaccess
的文件中(即在.php文件旁边)
*如果主Apache配置文件允许;它是可选的,但通常是启用的
mod_重写没有做什么
mod_rewrite并不会神奇地让你所有的URL变得“漂亮”。这是一个常见的误解。如果您的网站中有此链接:
<a href="/my/ugly/link.php?is=not&very=pretty">
结合转换传出的HTML页面及其包含的链接。虽然这通常比更新HTML资源更费劲。)
mod_rewrite可以做很多事情,您可以创建非常复杂的匹配规则,包括链接多个重写,将请求代理到完全不同的服务或机器,返回特定的HTTP状态码作为响应,重定向请求等。它非常强大,如果您了解基本的HTTP请求-响应机制,就可以很好地使用它。它不会自动让你的链接变得漂亮
有关所有可能的标志和选项,请参见。要进一步展开,我想提供一些示例并解释一些其他mod_重写功能
以下所有示例都假设您已经在.htaccess
文件中包含了RewriteEngine On
重写示例
让我们举一个例子:
RewriteRule ^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$ /blog/index.php?id=$1&title=$2 [NC,L,QSA]
该规则分为4个部分:
# Apache 2.2
RewriteLogLevel 5
RewriteLog /tmp/rewrite.log
# Apache 2.4
LogLevel alert rewrite:trace5
#ErrorLog /tmp/rewrite.log
重写规则
-启动重写规则
^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$
-这称为模式,但我将其称为规则的左侧-您要从中重写的内容
blog/index.php?id=$1&title=$2
-称为替换,或重写规则的右侧-您要重写的内容
[NC,L,QSA]
是重写规则的标志,用逗号分隔,我将在后面详细解释
上面的重写将允许您链接到类似于/blog/1/foo/
的内容,它将实际加载/blog/index.php?id=1&title=foo
规则的左边
^
指示页面名称的开头-因此它将重写example.com/blog/…
,但不会重写e
# if the host doesn't start with www. then add it and redirect
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# if it cant find the image, try find the image on another domain
RewriteCond %{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)$ http://www.example.com/$1 [L]
http://example.com/script.php/virtual/path
Options +MultiViews
DefaultType application/x-httpd-php
<Files article>
SetHandler application/x-httpd-php
# or SetType
</Files>
RewriteRule ^contact$ templ/contact.html
RewriteRule ^about$ about.php
RewriteRule ^article/(\d+)$ article-show.php?id=$1
# └───────────────────────────┘
RewriteRule ^article/([\w-]+)$ article-show.php?title=$1
# └────────────────────────────────┘
RewriteRule ^article/(\d+)-([\w-]+)$ article.php?id=$1&title=$2
# └───────────────────────────────┘
# ┌─────────────────────────┐
RewriteRule ^(blog|post|user)/(\w+)$ disp.php?type=$1&id=$2
# └───────────────────────────────────┘
# ┌─────────────────────────────┐
# │ ┌───────────┼───────────────┐
RewriteRule ^blog/(2009|2010|2011)/([\d-]+)/?$ old/blog.php?date=$2
RewriteRule ^blog/(\d+)/([\d-]+)/?$ modern/blog/index.php?start=$2
# └──────────────────────────────────────┘
RewriteRule ^user-(\d+)$ show.php?what=user&id=$1
# └──────────────────────────────┘
# This could use `(\w+)` alternatively for user names instead of ids.
RewriteRule ^wiki:(\w+):(\w+)$ wiki.php?sect=$1&page=$2
# └─────┼────────────────────┘ │
# └────────────────────────────┘
RewriteRule ^blog/([\w-]+)/?$ blog/show.php?id=$1
# ┗┛
Rewriterule ^(\w+)/?$ in.php?a=$1
Rewriterule ^(\w+)/(\w+)/?$ in.php?a=$1&b=$2
Rewriterule ^(\w+)/(\w+)/(\w+)/?$ in.php?a=$1&b=$2&c=$3
# └─────┴─────┴───────────────────┴────┴────┘
RewriteRule ^(\w+)(?:/([^/]+))?/(\w+)$ ?main=$1&opt=$2&suffix=$3
RewriteRule ^(specific)/prefix/(\d+)(/.*)?$ speci.php?id=$2&otherparams=$2
RewriteRule ^styles/([\w\.\-]+)\.css$ sass-cache.php?old_fn_base=$1
RewriteRule ^images/([\w\.\-]+)\.gif$ png-converter.php?load_from=$2
# redirect browser for old/ugly incoming paths
RewriteRule ^old/teams\.html$ /teams [R=301,QSA,END]
# internally remap already-pretty incoming request
RewriteRule ^teams$ teams.php [QSA,END]
RewriteRule "^this [\w ]+/(.*)$" "index.php?id=$1" [L]
RewriteCond %{REQUEST_URI} !-f
RewriteCond %{REQUEST_URI} !-d
RewriteRule ^.*$ index.php [L]
# ┌──────────┐
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] │
RewriteRule ^(.*)$ http://%1/$1 [R=301,L] │
# ↓ └───┼────────────┘
# └───────────────┘
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://example.com/$1 [R,L]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ $1.php [L] # or [END]
RewriteRule ^/article/\d+$ …
↑
<IfModule mod_rewrite.c>
Rewrite…
</IfModule>
RewriteCond %{SERVER_NAME} localhost
RewriteRule ^secret admin/tools.php
RewriteRule ^hidden sqladmin.cgi
RewriteCond %{QUERY_STRING} \b(?:param)=([^&]+)(?:&|$)
RewriteRule ^add/(.+)$ add/%1/$1 # ←──﹪₁──┘
# Apache 2.2
RewriteLogLevel 5
RewriteLog /tmp/rewrite.log
# Apache 2.4
LogLevel alert rewrite:trace5
#ErrorLog /tmp/rewrite.log
[..] applying pattern '^test_.*$' to uri 'index.php'
[..] strip per-dir prefix: /srv/www/vhosts/hc-profi/index.php -> index.php
[..] applying pattern '^index\.php$' to uri 'index.php'
RewriteRule my-blog/(\d+)--i-found-the-answer my-blog/entry.php?id=$1
RewriteRule my-blog/entry.php?id=(\d+) my-blog/$1--i-found-the-answer [R]
RewriteRule my-blog/entry.php?id=(\d+) my-blog/i-found-the-answer [R]