abcfy2 发表于 2013-04-15 23:07

apache手册中rewrite功能中RewriteRule的疑问[已解决]

本帖最后由 abcfy2 于 2013-04-18 16:26 编辑

虚拟用户主机

描述:
如果需要为用户username支持一个www.username.host.domain.com的主页,但不在此机器上建虚拟主机,而是仅用在此机器上增加一个DNS A记录的方法实现。
解决方案:
仅能对包含"Host: "头的HTTP/1.1请求实现。可以使用以下规则集内部地将http://www.username.host.com/anypath重写为/home/username/anypath
RewriteEngine on
RewriteCond   %{HTTP_HOST}               ^www\.[^.]+\.host\.com$
RewriteRule   ^(.+)                        %{HTTP_HOST}$1         
RewriteRule   ^www\.([^.]+)\.host\.com(.*) /home/$1$2

apache的手册中的内容,
RewriteRule   ^(.+)                        %{HTTP_HOST}$1          这句怎么理解呢?
一直不能理解为什么要加这一句,而且测试过如果没有这一句下一句的跳转不成立,没效果。

另外问一下手册中怎么翻查apache的内建变量呢?至今只是自己测试+瞎猜知道有个%{HTTP_HOST}这个变量,用于获取URL中的域名部分,其他变量在哪查?具体的含义呢?

还想知道这些正则表达式的具体用法在apache手册怎么查到呢?翻遍了也没找到一个系统的教程,目前只知道()内的字符正则可以被$1,$2...$N来依序匹配获得

tzb12qaqa 发表于 2013-04-17 09:58

本帖最后由 tzb12qaqa 于 2013-04-17 10:12 编辑

是为了与下一条规则捆绑,当相应的RewriteRule匹配时,则继续下一条RewriteRule ,否则下一条将被忽略。
另外 RewriteRule 第一个正则表达式是不匹配域名的

The Pattern will initially be matched against the part of the URL after the hostname and port, and before the query string (e.g. "/app1/index.html").

RewriteRule   ^(.+)                        %{HTTP_HOST}$1         
是为了将域名加入到被匹配字符中去

请参考
http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewriterule
http://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_c
#变量名列表 (如果不了解变量名的含义,试着从HTTP协议入手)
http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewritecond

abcfy2 发表于 2013-04-18 13:35

回复 2# tzb12qaqa


    我知道C是代表chain,当前匹配才会继续下一条重写规则,但是不明白为什么RewriteRule   ^(.+)                        %{HTTP_HOST}$1         
^代表开始,"."代表任意单个字符,+代表"."至少匹配一次,那么这样写不就是匹配完整的URL请求么?比如http://www.a.com不就完整的匹配了这条规则?后面又重写成了www.a.comhttp://www.a.com??

还是意味着加上^代表匹配Location /以下的请求?这样的话这条重写岂不是没有任何的意义?仅仅是为了检查/下面还有没有附加别的请求?

abcfy2 发表于 2013-04-18 13:46

本帖最后由 abcfy2 于 2013-04-18 13:49 编辑

回复 2# tzb12qaqa


    仔细回味了一下,好像是这么个意思,RewriteRule是从/请求下面匹配的,这样就不能匹配到URL了,所以进行了重写,加上了%{HTTP_HOST}来进行下一条规则的重写。

我现在有这样的需求,前端用apache,后端用tomcat,做了一个apache+tomcat的反向代理整合,特殊需求如下:
1,要求用户强制使用https安全协议访问网站,也就是加不加https都强制跳转443端口的https协议
2,要求用户空主机头访问跳转到www主机头,也就是用户访问fy.com的时候跳转到www.fy.com
3,用户的目录在www.fy.com/username下,用户可以用自己的用户名代替主机头访问,如user1.fy.com实际访问的是www.fy.com/user1,用户感觉不到URL的变化,让用户感觉到类似于自己主页的效果。
4,用户自己将自己的域名访问也可以,比如www.user1.com,实际访问www.fy.com/user1

我根据需求写了如下的配置:
#80端口强制跳转443端口
<VirtualHost *:80>
      RewriteEngine On
      RewriteRule ^(.+)$ https://%{HTTP_HOST}$1
</VirtualHost>


<VirtualHost *:443>
      Options +FollowSymLinks
      ErrorLog ${APACHE_LOG_DIR}/error.log
      CustomLog ${APACHE_LOG_DIR}/access.log combined
      RewriteEngine on
      #空主机头显式跳转www主机头,如fy.com跳转到https://www.fy.com
      RewriteCond %{HTTP_HOST} ^fy.com$
      RewriteRule ^/(.*) https://www.fy.com/$1
      #对于主机头不是www的,跳转为https://www.fy.com/$1$2
      RewriteCond %{HTTP_HOST} !^www.fy.com$
      RewriteRule ^(.+)$ %{HTTP_HOST}$1
      RewriteRule ^(.+)\.fy\.com(.*)$ https://www.fy.com/$1$2
      #对于域名不是*.fy.com的,跳转为https://www.fy.com/$1$2
      RewriteCond %{HTTP_HOST} !^.*\.fy\.com$
      RewriteRule ^www\.(.*)\.com(.*) https://www.fy.com/$1$2
#       ServerName fengyu.com
      ProxyRequests Off
      SSLEngine On
      SSLCertificateFile /etc/ssl/private/apache.pem
#       SSLCertificateKeyFile /etc/apache2/server.key
      SSLProxyEngine off
      ProxyPass / http://127.0.0.1:8080/temp/
      ProxyPassReverse / http://127.0.0.1:8080/temp/
</VirtualHost>
现在问题就来了,为什么访问test.fy.com的时候,URL会显示跳转为https://www.fy.com/test呢?这不是我想要的结果,我想要用户访问test.fy.com,实际显示的页面是www.fy.com/test,但是用户的URL依然是test.fy.com,用户感觉不到页面跳转。这个问题在哪呢?应该怎么改?我的RewriteRule明明没有加R啊,应该不会成为重定向才对啊。

而且www.test.com也会跳转为www.fy.com/test

abcfy2 发表于 2013-04-18 15:32

本帖最后由 abcfy2 于 2013-04-19 17:24 编辑

回复 2# tzb12qaqa


    多谢指导了,我又仔细研读了一下手册(金步国翻译的中文手册),发现用P代理就可以解决自己的问题,最终修改如下:#80端口强制跳转443端口

<VirtualHost *:80>
    RewriteEngine On
    RewriteRule ^(.+)$ https://%{HTTP_HOST}$1
</VirtualHost>





<VirtualHost *:443>
    Options +FollowSymLinks
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    RewriteLogLevel 3 #这里可以去掉了,当时为了看rewrite调试过程的
    RewriteLog ${APACHE_LOG_DIR}/rewrite.log #这里可以去掉了,当时为了看rewrite调试过程的
    RewriteEngine on

#空主机头显式跳转www主机头,如fy.com跳转到https://www.fy.com
    RewriteCond %{HTTP_HOST} ^fy.com$
    RewriteRule ^/(.*) https://www.fy.com/$1 #R表示重定向,这样URL是显式的

#对于主机头不是www的进行反向代理,如test.fy.com会根据重写规则反向代理至http://127.0.0.1:8080/test

    RewriteCond %{HTTP_HOST} !^www.fy.com$
    RewriteRule ^(.+) %{HTTP_HOST}$1
    RewriteRule ^(.+)\.fy\.com(.*)$ http://127.0.0.1:8080/temp/$1$2 #用P反向代理,这样URL是不会跳转的

#对于不是*.fy.com这种的访问,如www.test.com,进行反向代理,规则同上,没有加RewriteRule ^(.+) %{HTTP_HOST}$1 因为www.test.com已经匹配了RewriteCond %{HTTP_HOST} !^www.fy.com$这条规则,已经进行了一次RewriteRule ^(.+) %{HTTP_HOST}$1
    RewriteCond %{HTTP_HOST} !^.*\.fy\.com$
    RewriteRule ^www\.(.*)\.com(.*) http://127.0.0.1:8080/temp/$1$2 #用P反向代理,这样URL是不会跳转的
    # ServerName fengyu.com
    ProxyRequests Off
    SSLEngine On
    SSLCertificateFile /etc/ssl/private/apache.pem
# SSLCertificateKeyFile /etc/apache2/server.key
    SSLProxyEngine off
    ProxyPass / http://127.0.0.1:8080/temp/
    ProxyPassReverse / http://127.0.0.1:8080/temp/
</VirtualHost>

abcfy2 发表于 2013-04-18 15:56

本帖最后由 abcfy2 于 2013-04-18 16:20 编辑

还有一事不明      RewriteCond %{HTTP_HOST} !^www.fy.com$
      RewriteRule ^(.+) %{HTTP_HOST}$1
      RewriteRule ^(.+)\.fy\.com(.*)$ http://127.0.0.1:8080/temp/$1$2 #用P反向代理,这样URL是不会跳转的这段规则中必须加上RewriteRule ^(.+) %{HTTP_HOST}$1 才能正确访问到代理的地址http://127.0.0.1:8080/temp/test/index.jsp

但是这里      RewriteCond %{HTTP_HOST} !^.*\.fy\.com$
      RewriteRule ^www\.(.*)\.com(.*) http://127.0.0.1:8080/temp/$1$2 #用P反向代理,这样URL是不会跳不能加上RewriteRule ^(.+) %{HTTP_HOST}$1 ,否则www.test.com返回错误是访问到了/temp/test.comwww.test/
这是为什么呢?


哦明白是咋回事了,www.test.com先匹配了RewriteCond %{HTTP_HOST} !^www.fy.com$这条规则,进行了一次重写RewriteRule ^(.+) %{HTTP_HOST}$1 ,而下面那条规则RewriteRule ^(.+)\.fy\.com(.*)$ http://127.0.0.1:8080/temp/$1$2 没有匹配到,所以跳过,进行下面的匹配,匹配到规则RewriteCond %{HTTP_HOST} !^.*\.fy\.com$,然后直接进行重写了 RewriteRule ^www\.(.*)\.com(.*) http://127.0.0.1:8080/temp/$1$2
页: [1]
查看完整版本: apache手册中rewrite功能中RewriteRule的疑问[已解决]