Apache 和 Nginx 下的 URL 重写
URL 重写和重定向
URL 重写是将页面映射到本站另一页面, 而重定向则是将页面映射到另一主机(域名). 其中临时重定向(R=302)和永久重定向(R=301)都是亲搜索引擎的, 是 SEO 的重要技术. 通过重定向, 浏览器和搜索引擎都意思到页面发生了变化, 从而分别改变地址栏显示的地址和更新搜索引擎索引.
Apache 中的 URL 重写和重定向
**参考文章: **
- https://stackoverflow.com/questions/704102/how-does-rewritebase-work-in-htaccess#
- http://lesca.me/archives/htaccess-rewrite.html/comment-page-1#comment-16045
- http://blog.csdn.net/lijunwyf/article/details/54948463
- http://blog.csdn.net/pursuing0my0dream/article/details/45028625
启用 Apache 的 URL 重写功能, 需要开启mod_rewrite
模块. 然后在服务器配置文件或.htaccess
中修改服务配置:
AllowOverride all
Options FollowSysLinks
服务器配置文件和.htaccess
文件中都可以配置 URL 重写. 前者是服务器级别, 后者是目录级别.
开启重写日志
2.4 以下版本
在 Apache 服务器配置文件中追加:
RewriteLog "自定义日志路径"
# 设置日志等级
RewriteLogLevel 9
等级 0 为关闭, 9 表示输出最详细信息.
2.4 及其以上版本
在 Apache 服务器配置文件中追加:
LogLevel alert rewrite:trace3
其中 trace3 可以替换为 trace1 到 trace8, 数值越大输出的信息越详细. 最后输出的日志信息在apache_error.log
文件中.
注意: 日志级别越高, 越影响服务器性能. 生产环境下应关闭重写日志.
重写指令
RewriteEngine
RewriteEngine
: 是否启用重写引擎. On
启用, Off
不启用.
RewriteBase
RewriteBase
: 设置重写的基准目录. 基准目录的根目录就是网站的根目录.
RewriteCond
RewriteCond
: 设置重写条件.
语法: RewriteCond TestString CondPattern [flags]
RewriteCond 指令定义一条规则条件。在一条 RewriteRule 指令前面可能会有一条或多条 RewriteCond 指令,只有 TestString 符合 CondPattern 时规则才被应用于当前URL处理。
TestString
是一个纯文本的字符串,除了包含普通的字符外,还可以包括下列的可扩展结构:
$N
: RewriteRule 后向引用,其中(0 <= N <= 9) .$N
引用紧跟在 RewriteCond 后面的 RewriteRule 中模板中的括号中的模板在当前 URL 中匹配的数据.%N
: RewriteCond 后向引用, 其中(0 <= N <= 9).%N
引用最后一个 RewriteCond 的模板中的括号中的模板在当前 URL 中匹配的数据.${mapname:key|default}
:RewriteMap 扩展。
CondPattern
是条件 pattern, 即一个应用于当前实例TestString 的正则表达式, 即 TestString 将会被计算然后与CondPattern 匹配. 作为一个标准的扩展正则式, CondPattern 有以下补充:
可以在模板串前增加一个
!
前缀,以表示不匹配模板。但并不是所有的 test 都可以加!
前缀。CondPattern中可以使用以下特殊变量:
>CondPattern
: 大于, 将 CondPattern 当作一个普通字符串, 将它和 TestString 进行比较, 当T estString 的字符大于CondPattern 为真.
=CondPattern
: 等于, 将 CondPattern 当作一个普通字符串,将它和TestString进行比较, 当 TestString 与 CondPattern 完全相同时为真. 如果 CondPattern 只是""
(两个引号紧挨在一起) 此时需 TestString 为空字符串方为真。
-d
: 是否为目录, 将 TestString 当作一个目录名, 检查它是否存在以及是否是一个目录.
-f
: 是否是 regular file, 将 TestString 当作一个文件名, 检查它是否存在以及是否是一个 regular 文件.
-s
: 是否为长度不为0的 regular文件, 将 TestString 当作一个文件名, 检查它是否存在以及是否是一个长度大于0的 regular 文件.
-l
: 是否为 symbolic link, 将 TestString 当作一个文件名, 检查它是否存在以及是否是一个 symbolic link.
-F
: 通过 subrequest 来检查某文件是否可访问. 检查 TestString 是否是一个合法的文件, 而且通过服务器范围内的当前设置的访问控制进行访问. 这个检查是通过一个内部 subrequest 完成的, 因此需要小心使用这个功能以降低服务器的性能.
-U
: 通过 subrequest 来检查某个 URL 是否存在. 检查 TestString 是否是一个合法的URL, 而且通过服务器范围内的当前设置的访问控制进行访问. 这个检查是通过一个内部 subrequest 完成的, 因此需要小心使用这个功能以降低服务器的性能.
[flags]
是第三个参数,多个标志之间用逗号分隔。
nocase|NC
: 不区分大小写. 在扩展后的 TestString 和 CondPattern 中, 比较时不区分文本的大小写. 注意, 这个标志对文件系统和 subrequest 检查没有影响.ornext|OR
: 建立与下一个条件的或的关系. 默认的情况下,二个条件之间是AND
的关系, 用这个标志将关系改为OR
. 例如:RewriteCond %{REMOTE_HOST} ^host1.* [OR]
RewriteCond %{REMOTE_HOST} ^host2.* [OR]
RewriteCond %{REMOTE_HOST} ^host3.*
RewriteRule …
如果没有[OR]
标志,需要写三个条件/规则.
RewriteRule
RewriteRule
: 设置重写规则.
语法: RewriteRule Pattern Substitution [flags]
.
Pattern
是一个作用于当前 URL 的兼容 perl 的正则表达式. 这里的“当前”是指该规则生效时的 URL 的值。Substitution
是当原始 URL 与 Pattern 相匹配时
, 用以替代(或替换)的字符串. (RewriteRule 中也会进行一次判断, 被捕获的 URL 是否与 Pattern相匹配)Substitution
还可以追加特殊标记[flags]
作为 RewriteRule 指令的第三个参数。 Flags 是一个包含以逗号分隔的下列标记的列表:
redirect|R[=code]
(强制重定向 redirect)
强制性执行一个外部重定向. 如果code没有指定, 则默认302. 如果需要使用在 300-400 范围内的其他响应代码, 只需在此指定这个数值即可. 另外, 还可以使用下列符号名称之一:temp
(默认的),permanent
,seeother
.注意: 在使用这个标记时,务必确保该替换字段是一个有效的 URL ! 并且要记住,如果希望停止重写操作而立即重定向,则还需要使用
L
标记.forbidden|F
(强制 URL 为被禁止的 forbidden )
强制当前 URL 为被禁止的, 立即反馈一个 403. 使用这个标记, 可以链接若干 RewriteConds 以有条件地阻塞某些 URL.gone|G
(强制 URL 为已废弃的 gone )
强制当前URL 为已废弃的, 立即反馈一个 410. 使用这个标记, 可以标明页面已经被废弃而不存在了.proxy|P
(强制为代理 proxy )
此标记使替换成分被内部强制为代理请求, 并立即(重写规则处理立即中断)把处理移交给代理模块. 你必须确保此替换串是一个有效的, 能够为 Apache 代理模块所处理的 URI. 使用这个标记, 可以把某些远程成分映射到本地服务器名称空间, 从而增强了 ProxyPass 指令的功能。注意: 要使用这个功能, 代理模块必须编译在Apache服务器中. 不能确定, 可以检查
httpd -l
的输出中是否有mod_proxy.c
. 如果有, 则mod_rewrite
可以使用这个功能; 如果没有, 则必须启用mod_proxy
并重新编译httpd
程序.last|L
(最后一个规则 last)
立即停止重写操作, 并不再应用其他重写规则. 它对应于 Perl中 的last
命令或C语言中的break
命令. 这个标记可以阻止当前已被重写的 URL 为其后继的规则所重写.next|N
(重新执行 next round)
重新执行重写操作(从第一个规则重新开始). 这时再次进行处理的URL已经不是原始的URL, 而是经最后一个重写规则处理的URL. 它对应于 Perl 中的next
命令或C语言中的continue
命令. 此标记可以重新开始重写操作, 即立即回到循环的头部.chain|C
(与下一个规则相链接 chained)
此标记使当前规则与下一个(其本身又可以与其后继规则相链接的, 并可以如此反复的)规则相链接. 它产生这样一个效果: 如果一个规则被匹配, 通常会继续处理其后继规则, 即这个标记不起作用; 如果规则不能被匹配, 则其后继的链接的规则会被忽略. 比如, 在执行一个外部重定向时, 对一个目录级规则集, 你可能需要删除".www" (此处不应该出现".www"的).type|T=MIME-type
(强制MIME类型 type)
强制目标文件的 MIME 类型为 MIME-type. 比如, 它可以用于模拟 mod_alias 中的 ScriptAlias 指令, 在内部强制被映射目录中的所有文件的 MIME 类型为"application/x-httpd-cgi".nosubreq|NS
(仅用于不对内部子请求进行处理 no internal sub-request)
在当前请求是一个内部子请求时, 此标记强制重写引擎跳过该重写规则. 比如, 在 mod_include 试图搜索可能的目录默认文件(index.xxx)时, Apache 会在内部产生子请求. 对子请求, 它不一定有用的, 而且如果整个规则集都起作用, 它甚至可能会引发错误. 所以, 可以用这个标记来排除某些规则.nocase|NC
(忽略大小写 no case)
它使 Pattern 忽略大小写.qsappend|QSA
(追加请求串 query string append)
此标记强制重写引擎在已有的替换串中追加一个请求串, 而不是简单的替换. 如果需要通过重写规则在请求串中增加信息, 就可以使用这个标记.noescape|NE
(在输出中不对URI作转义 no URI escaping)
此标记阻止 mod_rewrite 对重写结果应用常规的 URI 转义规则. 一般情况下, 特殊字符(如%
,$
,;
等)会被转义为等值的十六进制编码. 此标记可以阻止这样的转义, 允许百分号等符号出现在输出中,如:RewriteRule /foo/(.*) /bar?arg=P1=$1 [R,NE] 可以使’/foo/zed’转向到一个安全的请求’/bar?arg=P1=zed’.
passthrough|PT
(移交给下一个处理器 pass through)
让 mod_rewrite 模块将重写的 URL 传回给 Apache 做进一步处理.skip|S=num
(跳过后继的规则 skip)
如果满足某指定的条件,则跳过后面第 num 调规则.env|E=variable:value
(设置环境变量 environment variable)
此标记使环境变量 variable 的值为 value, VAL可以包含可扩展的反向引用的正则表达式$N
和%N
. 此标记可以多次使用以设置多个变量。这些变量可以在后继的 RewriteCond 指令的pattern 中通过%{ENV:VAR}
作引用. 。cookie|CO=NAME:VAL:domain[:lifetime[:path]]
(设置cookie)
在客户端浏览器上设置一个cookie. cookie 的名称是 NAME, 值是 VAL. domain字段是该 cookie 的域, 比如'.apache.org', 可选的 lifetime 是 cookie 生命期的分钟数, 可选的 path 是 cookie 的路径.
在 .htaccess 文件中配置重写规则
在.htaccess
文件中使用重写功能时, RewriteRule 负责匹配的 URI 是相对.htaccess
所在的目录而言的.
例如访问 http://example.com/subdir1/subdir2/subdir3:
- 如果
.htaccess
在网站根目录下, 那么RewriteRule
捕获的 URI 是subdir1/subdir2/subdir3
. - 如果
.htaccess
在 subdir1 目录下,RewriteRule
捕获的 URI 是subdir2/subdir3
.
RewriteRule
重写 URI 后的基准目录也是以.htaccess
所在的目录为准. 例如: 访问 http://example.com/foo
RewriteRule ^foo$ bar.php [L]
如果.htaccess
在根目录下, 重写后访问 http://example.com/bar.php. 如果在 subdir1 目录下, 重写后访问 http://example.com/subdir1/bar.php.
例 1:
<IfModule mod_rewrite.c>
# 启用rewrite引擎
RewriteEngine On
# 重写规则: 匹配任意以htm后缀的文件, 将htm替换成php. ^(.*)\.htm$ 是一个正则表达式, 表示需要重写的部分, 此处指以任意字符开头, 以.htm结尾的部分. $1.php 是一个重写规则, $1 表示匹配到正则表达式中第一个子模式的字符串. [NC]: 表示重写规则如何应用, 该处表示不区分大小写. 整条规则即重写以任意字符开头, 以.htm结尾的部分, 重写为由匹配到的第一个子模式字符串和.php拼接成的字符串.
RewriteRule ^(.*)\.htm$ $1.php [NC]
</IfModule>
IfModule 命令用于判断是否安装了 mod_rewrite 模块.
例 2:
<IfModule mod_rewrite.c>
RewriteEngine On
# 设置目录级重写的基准URI
RewriteBase /subdir1/
RewriteRule ^(.*)\.htm$ $1.php [NC,L,R]
</IfModule>
RewriteBase
设置了重写的基准目录. 如果上例中.htaccess
位于网站根目录下, 访问的 http://example.com/foo.htm, 原本重写后的基准目录是网站根目录/
, 设置了RewriteBase
后变为/subdir1/
, 重写后实际访问 http://example.com/subdir1/foo.php.- 规则标志
L
: 表示如果可以匹配本条规则, 则不再继续往下匹配. - 规则标志
R
: 表示临时重定向, 即 302, 相当于[R=302]
.
例 3:
<IfModule mod_rewrite.c>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} (localhost:81)
RewriteRule ^(.*) http://localhost:82 [R=301]
</IfModule>
[R=301]
: 表示永久性重定向, 用户发送的所有请求都会被发送到新域名处理. 永久重定向到另一个域名使用了绝对 URI, 因此不用再设置 RewriteBase.%{HTTP_HOST}
: 表示引用 Apache 服务器变量 HTTP_HOST.- 该条 RewriteCond 表示判断 HTTP_HOST 是否是 localhost:81.
在 httpd.conf 中配置重写规则
在服务器配置文件中配置 URL 重写的指令与 .htaccess 文件中的格式相同. 需要写在<Directory>
内.
Nginx
**参考文章: **
- https://www.cnblogs.com/likwo/p/6513117.html
- http://blog.csdn.net/u012486840/article/details/52787232
Nginx 的 URL 重写功能不需要额外的支持. Nginx 本身只支持在服务器配置文件中配置 URL 重写规则, 不支持 .htaccess 文件. 但可以通过在服务器配置文件中引入外部文件的方式, 实现对 .htaccess 文件的支持. 这会严重影响 Nginx 的性能.
重写指令
rewrite
根据重写规则, 重写 URL.
语法: rewrite regex replacement flag
应用环境: server
, location
, if
可应用的 flag 标记包括:
last
: 相当于 Apache 中的L
标记.break
: 终止匹配, 不再匹配后面的规则.redirect
: 临时重定向, 返回 302.permanent
: 永久性重定向, 返回 301.
示例:
rewrite ^(.*)\.html$ $1.php last;
注意: 如果访问的是 http://localhost/dir/file, rewrite 中的正则表达式匹配的是 /dir/file, 包括最左边的正斜杠.
if 指令
语法: if (condition){...}
注意
if
之后紧跟的空格不能省略.
应用环境: server
, location
判断一个条件是否符合, 如果符合, 则执行大括号内语句. if 指令不支持嵌套, 不支持&&
和||
操作.
condition
中可以包含如下判断表示:
~
: 区分大小写进行匹配~*
: 不区分大小写进行匹配!~
: 区分大小写进行非
匹配!~*
: 不区分大小写进行非
匹配-f
: 如果文件存在!-f
: 如果文件不存在-d
: 如果目录存在!-d
: 如果目录不存在-e
: 如果文件或目录存!-e
: 如果文件或目录不存在-x
: 如果文件可执行!-x
: 如果文件不可执行
示例:
location ~ \.html$ {
if (!-f $request_filename)
{
rewrite (.*)\.html$ $1.php last;
}
}
访问的 URL 以.html
结尾时, 判断是否存在该文件, 如果不存在就重写为访问同名的 PHP 脚本.
return 指令
语法: return code
应用环境: server
, location
, if
该指令用于结束规则的执行并返回状态码给客户端.
例如:
return 403;
location 指令
语法: location [flags] regex
应用环境: server
flags
包括:
~
: 执行一个正则匹配, 区分大小写
~*
: 执行一个正则匹配, 不区分大小写
^~
: 表示普通字符匹配. 使用前缀匹配成功. 如果匹配成功, 则不再匹配其他 location.
=
: 进行普通字符完全匹配.
优先级:
=
的优先级最高. 匹配成功后, 不再匹配其他项.^~
类型表达式. 匹配成功后, 不再匹配其他项.~
和~*
. 如果有多个 location 的正则匹配.- 常规字符串匹配类型, 按前缀匹配.
rewrite_log 指令
语法: rewrite_log on|off
应用环境: server
, location
, if
启用时, 将在error_log
中记录 notice 级别的重写日志.
set 指令
语法: set variable value
应用环境: server
, location
, if
为给定的变量设置一个特定值.
Nginx 内置的全局变量
$args
: 这个变量等于请求行中的参数, 同 $query_string.
$content_length
: 请求头中的 Content-length 字段.
$content_type
: 请求头中的 Content-Type 字段.
$document_root
: 当前请求在 root 指令中指定的值.
$host
: 请求主机头字段,否则为服务器名称.
$http_user_agent
: 客户端 agent 信息.
$http_cookie
: 客户端 cookie 信息.
$limit_rate
: 这个变量可以限制连接速率.
$request_method
: 客户端请求的动作,通常为 GET 或 POST.
$remote_addr
: 客户端的 IP 地址.
$remote_port
: 客户端的端口.
$remote_user
: 已经经过 Auth Basic Module 验证的用户名.
$request_filename
: 当前请求的文件路径, 由 root 或 alias 指令与 URI 请求生成.
$scheme
: HTTP 方法(如 http, https).
$server_protocol
: 请求使用的协议, 通常是HTTP/1.0 或 HTTP/1.1.
$server_addr
: 服务器地址, 在完成一次系统调用后可以确定这个值.
$server_name
: 服务器名称.
$server_port
: 请求到达服务器的端口号.
$request_uri
: 包含请求参数的原始 URI, 不包含主机名, 如: ”/foo/bar.php?arg=baz”.
$uri
: 不带请求参数的当前 URI, $uri 不包含主机名, 如 "/foo/bar.html".
$document_uri
: 与$uri相同.
Apache 和 Nginx 下的 URL 重写的更多相关文章
- nginx 常用的 URL 重写方法
转自:http://www.jbxue.com/article/4727.html Nginx中一些常用的URL 重写方法介绍,有需要的朋友可以参考下.url重写应该不陌生,不管是SEO URL 伪静 ...
- Nginx – rewrite 配置 URL重写及301跳转原理图
Nginx – rewrite 配置 URL重写 官网:http://nginx.org/en/docs/http/ngx_http_rewrite_module.html 语法:rewrite re ...
- 客户端禁用cookie情况下的URL重写
客户端禁用cookie情况下的URL重写: servlet: package com.stono.servlet.listenerorder; import java.io.IOException; ...
- (Nginx和PHP下)URL重写,TP实现URL重写
UrlRewrite就是我们通常说的地址重写,用户得到的全部都是经过处理后的URL地址. 优点 一:提高安全性,可以有效的避免一些参数名.ID等完全暴露在用户面前,如果用户随便乱输的话,不符合规则的话 ...
- Apache和Nginx下禁止访问特定的目录或文件
大家是否测试Apache做了目录禁止浏览后,目录下面的txt文件还是可以显示里面的内容的.例如:http://www.domain.com/test/此访问会报403错误,但是如果test下有很多tx ...
- IIS下 Yii Url重写
下载URL重写组件 http://www.microsoft.com/zh-cn/download/details.aspx?id=7435 导入官方提供的.htaccess文件 Options +F ...
- Linux下部署URL重写
在将项目部署在Linux服务器后可以通过URL重写隐藏应用的入口文件index.php cd /etc/apache2 vi apache2.conf 修改以下内容 将none改成Alll 重启服务 ...
- thinkphp 3.2.3在nginx+php下的url重写配置经验
环境:centos7.2+lnmp1.3(nginx+php7.0+mysql5.5) 进入服务器配置路径:cd /usr/local/nginx/conf/nginx.conf 修改nginx.co ...
- 在phpstudy集成环境下的nginx服务器下配置url重写
直接在对应的vhosts.conf配置文件的location / {}中添加以下内容: location / { index index.html index.htm index.php; #auto ...
随机推荐
- APDU命令的结构和处理【转】
本文转载自:http://blog.csdn.net/yonghenzhita/article/details/36402525 版权声明:本文为博主原创文章,未经博主允许不得转载. 简单说,IFD( ...
- 【转】Material Design 折叠效果 Toolbar CollapsingToolbarLayout AppBarLayout
我非常喜欢Material Design里折叠工具栏的效果,bilibili Android客户端视频详情页就是采用的这种设计.这篇文章的第二部分我们就通过简单的模仿bilibili视频详情页的实现来 ...
- mac系统下的常用命令
这是我日常在mac下记录的一些常用终端命令: 1 java 2 javac 3 exit 4 /Users/lianxumac/Desktop/apktool1.5.2/反编译 ; exit; 5 / ...
- 10.04 FZSZ模拟Day1 总结
今天轮到FZSZ出题了,这可是连续两年捧杯NOI的学校了…… 可想而知今天题难度有多大……不过似乎还要庆幸出题的是一位叫Anzhe Wang 的大神而不是fjzzq? T1.permutation 期 ...
- 10 探索其他Excel对象
10.1 产生一个好的第一印象 10.1.1 为我们的世界着色 rgb(red:=[0,225],green:=[0,225],blue:=[0,225]) 此函数生成一个表示颜色的整数.VBA预定义 ...
- Cpp module
- bzoj 1704: [Usaco2007 Mar]Face The Right Way 自动转身机【贪心+差分】
首先O(n^3)的贪心很好想,就是枚举k然后从前往后扫,扫到反就翻转区间 然后考虑优化掉翻转区间维,就是搞成差分的形式,在翻转区间的尾部打上标记,再用一个变量维护当前的翻转次数,加到当前状态上来判断是 ...
- bzoj 1782: [Usaco2010 Feb]slowdown 慢慢游【dfs序+线段树】
考虑每头牛到达之后的影响,u到达之后,从1到其子树内的点需要放慢的都多了一个,p为u子树内点的牛ans会加1 用线段树维护dfs序,每次修改子树区间,答案直接单点查询p即可 #include<i ...
- (DP)51NOD 1049 最大子段和
N个整数组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续子段和的最大值.当所给的整数均为负数时和为0. 例如:-2,11,-4,13,-5 ...
- WinForm ListBox 控件用法
下面演示如何利用列表控件 ListBox 实现多选与移动选项: using IMS.WinFormClient.UserControls; using System; using System.Col ...