搜索

首页  >  问答  >  正文

解释:理解 mod_rewrite、URL 重写和创建“漂亮的链接”

“漂亮的链接”是一个经常被要求的主题,但很少得到充分的解释。 mod_rewrite 是制作“漂亮链接”的一种方法,但它很复杂,语法也非常简洁,很难理解,并且文档假定您对 HTTP 有一定的熟练程度。有人可以简单地解释一下“漂亮链接”是如何工作的以及如何使用 mod_rewrite 来创建它们吗?

其他常用名称、别名、干净 URL 的术语:RESTful URL、用户友好 URL、SEO 友好 URL、slugging 和 MVC URL(可能用词不当)

P粉501007768P粉501007768402 天前769

全部回复(2)我来回复

  • P粉276064178

    P粉2760641782023-10-21 11:08:48

    为了扩展deceze的答案,我想提供一些示例和一些其他 mod_rewrite 功能的解释。

    以下所有示例均假设您已在 .htaccess 文件中包含 RewriteEngine On

    重写示例

    让我们举个例子:

    RewriteRule ^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$ /blog/index.php?id=&title= [NC,L,QSA]

    该规则分为 4 个部分:

    1. RewriteRule - 启动重写规则
    2. ^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$ - 这称为模式,但是我'只需将其称为规则的左侧 - 您想要重写的内容
    3. blog/index.php?id=$1&title=$2 - 称为替换,或重写规则的右侧 - 您想要重写的内容
    4. [NC,L,QSA] 是重写规则的标志,以逗号分隔,稍后我将详细解释

    上面的重写将允许您链接到类似 /blog/1/foo/ 的内容,并且它实际上会加载 /blog/index.php?id=1&title=foo.

    规则的左侧

    • ^ 表示页面名称的开头 - 因此它将重写 example.com/blog/... 但不会重写 example.com/foo/博客/...
    • 每组(…)括号代表一个正则表达式,我们可以将其捕获为规则右侧的变量。在这个例子中:
      • 第一组括号 - ([0-9]+) - 匹配长度至少为 1 个字符且仅包含数字值(即 0-9)的字符串。这可以通过规则右侧的 $1 引用
      • 第二组括号匹配长度至少为 1 个字符的字符串,仅包含字母数字字符(A-Z、a-z 或 0-9)或 -+ (注意 + 用反斜杠转义,因为如果不转义它,这将作为 正则表达式重复字符)。这可以通过规则右侧的 $2 引用
    • ? 表示前面的字符是可选的,因此在本例中 /blog/1/foo//blog/1/foo code> 将重写到同一位置
    • $ 表示这是我们要匹配的字符串的结尾

    标志

    这些选项添加在重写规则末尾的方括号中,用于指定某些条件。同样,您可以在文档中阅读许多不同的标志< /a>,但我将介绍一些更常见的标志:

    NC

    无大小写标志意味着重写规则不区分大小写,因此对于上面的示例规则,这意味着 /blog/1/foo//BLOG/1/ foo/ (或其任何变体)将被匹配。

    L

    最后一个标志表明这是应该处理的最后一条规则。这意味着当且仅当该规则匹配时,在当前重写处理运行中不会评估进一步的规则。如果规则不匹配,则将照常尝试所有其他规则。如果您不设置 L 标志,则随后的所有规则都将应用于重写的 URL。

    END

    自 Apache 2.4 起,您还可以使用 [END] 标志。与之匹配的规则将完全终止进一步的别名/重写处理。 (而 [L] 标志通常会触发第二轮,例如在重写子目录或重写子目录时。)

    QSA

    查询字符串追加标志允许我们将额外的变量传递到指定的 URL,这些变量将添加到原始的 get 参数中。对于我们的示例,这意味着像 /blog/1/foo/?comments=15 这样的内容将加载 /blog/index.php?id=1&title=foo&comments=15< /p>

    R

    这个标志不是我在上面的示例中使用的标志,但我认为值得一提。这允许您指定 http 重定向,并可以选择包含状态代码(例如 R=301)。例如,如果您想在 /myblog/ 上执行 301 重定向到 /blog/,您只需编写如下规则:

    RewriteRule ^/myblog/(*.)$ /blog/ [R=301,QSA,L]

    重写条件

    重写条件使重写更加强大,允许您指定针对更具体情况的重写。您可以在文档,但我将介绍一些常见示例并对其进行解释:

    # 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]

    这是一种非常常见的做法,它将在您的域名前面添加 www. (如果尚不存在)并执行 301 重定向。例如,加载 http://example.com/blog/ 会将您重定向到 http://www.example.com/blog/

    # 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/ [L]

    这种情况稍微不太常见,但这是一个很好的示例,说明如果文件名是服务器上存在的目录或文件,则不会执行该规则。

    • %{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC] 只会对文件扩展名为 jpg、jpeg、gif 或 png 的文件执行重写(大小写为不敏感)。
    • %{REQUEST_FILENAME} !-f 将检查当前服务器上是否存在该文件,如果不存在则执行重写
    • %{REQUEST_FILENAME} !-d 将检查当前服务器上是否存在该文件,如果不存在则执行重写
    • 重写将尝试加载另一个域上的相同文件

    回复
    0
  • P粉022140576

    P粉0221405762023-10-21 00:43:03

    要了解 mod_rewrite 是什么,您首先需要了解 Web 服务器的工作原理。 Web 服务器响应 HTTP 请求。最基本级别的 HTTP 请求如下所示:

    GET /foo/bar.html HTTP/1.1

    这是浏览器向 Web 服务器请求 URL /foo/bar.html 的简单请求。需要强调的是,它并不请求文件,它只是请求一些任意的 URL。该请求也可能如下所示:

    GET /foo/bar?baz=42 HTTP/1.1

    这与 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 的请求时,您可以将该 URL 重写为其他内容,然后 Web 服务器会在磁盘上查找匹配的文件它。简单的例子:

    RewriteEngine On
    RewriteRule   /foo/bar /foo/baz

    此规则表示只要请求匹配“/foo/bar”,请将其重写为“/foo/baz”。然后该请求将被处理,就像/foo/baz<相反,已请求 /code>。这可用于各种效果,例如:

    RewriteRule (.*) .html

    此规则匹配任何内容 (.*) 并捕获它 ((..)),然后重写它以附加“.html” ”。换句话说,如果 /foo/bar 是请求的 URL,则将按照 /foo/bar.html 已被请求的方式进行处理。有关正则表达式匹配、捕获和替换的详细信息,请参阅 http://regular-expressions.info

    另一个经常遇到的规则是:

    RewriteRule (.*) index.php?url=

    这再次匹配任何内容并将其重写到文件index.php,并在 url 查询参数中附加最初请求的 URL。即,对于传入的任何和所有请求,都会执行文件index.php,并且该文件将有权访问 $_GET['url'] 中的原始请求,因此它可以做任何它想做的事情有了它。

    首先,您将这些重写规则放入您的网络服务器配置文件中。 Apache 还允许*您将它们放入文档根目录中名为 .htaccess 的文件中(即 .php 文件旁边)。

    * 如果主 Apache 配置文件允许;它是可选的,但通常会启用。

    mod_rewrite 不做什么

    mod_rewrite 不会神奇地使所有 URL 变得“漂亮”。这是一个常见的误解。如果您的网站中有此链接:

    mod_rewrite 无法使之变得漂亮。为了使其成为一个漂亮的链接,您必须:

    1. 将链接更改为漂亮的链接:

    2. 使用上述任何一种方法,在服务器上使用 mod_rewrite 来处理对 URL /my/pretty/link 的请求。

    (可以使用mod_substitute< /a> 结合转换传出的 HTML 页面及其包含的链接。尽管这通常比仅仅更新 HTML 资源更费力。)

    mod_rewrite 可以做很多事情,您可以创建非常复杂的匹配规则,包括链接多个重写、将请求代理到完全不同的服务或机器、返回特定的 HTTP 状态代码作为响应、重定向请求等。它非常强大,可以如果您了解基本的 HTTP 请求响应机制,将会非常有用。它不会自动使您的链接变得漂亮。

    请参阅官方文档了解所有可能的标志和选项。

    回复
    0
  • 取消回复