在IIS7中使用ARR(Application Request Routing)反向代理虚拟目录到Nodejs站点

目标:

 1.访问www.arrdemo.com/proxy 跳转到 localhost:8898的Nodejs站点

 2.Nodejs站点的页面可以返回到浏览器,包括js,css,图片

 3.Nodejs站点的 res.redirect(' ') 重定向要正确,包括站内跳转和站外跳转

步骤:

1. 新建站点绑定域名www.arrdemo.com,配置host文件指向本机,新建虚拟目录proxy。  

注意去掉虚拟目录->压缩->"启用动态内容压缩"和“启用静态内容压缩” 前面的勾选。否则会出现如下错误:

HTTP 错误 500.52 - URL Rewrite Module Error.

HTTP 响应的内容已编码(“gzip”)时,无法应用出站重写规则。

  2.启动Nodejs站点 http://localhost:8898

  这个站点是《nodejs开发指南》上的microblog实例,学习过程中改成了Express4.13.1版本。

  3.安装ARR,启用Proxy

   下载地址(http://www.iis.net/downloads/microsoft/application-request-routing)

  安装完成后,打开IIS->选中服务器名称->双击 右侧功能视图 IIS 节点下的Application Request Routing Cache->点击 右侧操作视图Proxy节点下的Server Proxy Settings->勾选上Enable Proxy前面的复选框

     

 

 

 

 

 4.配置虚拟目录的URL重写规则

  在IIS节点,站点节点,虚拟目录节点都可以配置URL重新规则,并且一级级继承。配置完成后信息保存到对应的web.config文件中。所以如果www.arrdemo.com部署在多个服务器上,每个服务器的proxy虚拟目录都需要重定向时可以采取拷贝proxy下的web.config文件的方式快速部署。这里只在proxy虚拟目录下部署,排除继承的影响。

 首先,配置入站规则。把http://www.arrdemo.com/proxy/reg 这样的url重写成 http://localhost:8898/reg

 

双击"URL重写",从入站规则下选择空白规则模板。剩下的注意细看图片注释:

到这一步正常情况下在浏览器里输入http://www.arrdemo.com/proxy,应该可以看到有内容输出了,但是没有任何样式和js效果。如下图:

这是因为入站规则能把请求转发到nodejs里,nodejs返回的html内容再转发到浏览器。但html里的css和js还有图片的路径一般都是相对站点根路径的,不会加上虚拟目录proxy,所以前端看不到任何样式。

这时候该出站规则上场了。。。。。。。

 然后,配置出站规则。把http://localhost:8898/bootstrap/..... 这样的url转换成http://www.arrdemo.com/proxy/bootstrap/.....

我这里就拿已经配置好的规则演示了。规则多了分先后顺序,如果匹配上了是否”停止处理“很重要。比如:匹配上两个重新类型的规则,那么就会在输出里出现proxy/proxy的情形,导致出错。

第一个规则 bbbb,处理输出的js、css、图片等路径不对问题。

 

做完第一个规则,本应万事大吉,只剩喝酒了。然而。。。。然而。。。。。打开网页登陆后跳转到首页的地址变成了 www.arrdemo.com 没有加上proxy。接着下一规则走起。。。

第二个规则处理res.redirect('/'); 这种站内跳转 

站内跳转需要在输出时添加proxy,主要是检查  {RESPONSE_STATUS} 变量为302, 然后在 重写时输出 /proxy{R:1},规则如下(请细看图):

这样处理后站内跳转的就没问题了。

 

第三个规则处理res.redirect('http://www.baidu.com'); 这种站外跳转

  跟第二个规则的区别就是这种跳转不做任何操作,直接抛出,规则如下:

现在再去浏览器里访问一下试试吧,如果还不行,请重启站点。

总结:

1.完整的配置文件奉上

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <outboundRules>
                <clear />
                <rule name="bbbbb" enabled="true" stopProcessing="false">
                    <match filterByTags="A, Area, Base, Form, Frame, Head, Img, Input, Link, Script" pattern="^(.*)" />
                    <conditions logicalGrouping="MatchAny" trackAllCaptures="true">
                        <add input="{URL}" pattern="^/proxy.*" />
                    </conditions>
                    <action type="Rewrite" value="/proxy{R:1}" />
                </rule>
                <rule name="站外重定向" enabled="true" stopProcessing="true">
                    <match serverVariable="RESPONSE_LOCATION" pattern="^http://[^/]+/(.*)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="true">
                        <add input="{RESPONSE_STATUS}" pattern="^302" />
                    </conditions>
                    <action type="None" />
                </rule>
                <rule name="站外跳转2" enabled="true" stopProcessing="true">
                    <match serverVariable="RESPONSE_LOCATION" pattern="^https://[^/]+/(.*)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="true">
                        <add input="{RESPONSE_STATUS}" pattern="^302" />
                    </conditions>
                    <action type="None" />
                </rule>
                <rule name="站内从定向" enabled="true">
                    <match serverVariable="RESPONSE_LOCATION" pattern="^(.*)" />
                    <conditions logicalGrouping="MatchAny" trackAllCaptures="true">
                        <add input="{RESPONSE_STATUS}" pattern="^302" />
                    </conditions>
                    <action type="Rewrite" value="/proxy{R:1}" />
                </rule>
            </outboundRules>
            <rules>
                <remove name="aaaaa" />
                <rule name="aaaaa" stopProcessing="true">
                    <match url="^(.*)" />
                    <conditions />
                    <serverVariables />
                    <action type="Rewrite" url="http://localhost:8898/{R:1}" logRewrittenUrl="true" />
                </rule>
            </rules>
        </rewrite>
        <urlCompression doStaticCompression="false" doDynamicCompression="false" />
    </system.webServer>
</configuration>
proxy 下的 web.config

2.查找资料除了百度、必应最应该想到的就是官网帮助文档

每一步操作右侧都有个帮助的链接,点进去是详细的英文文档。

不过也不要完全相信,比如配置重定向跳转时,文档里是这样的:

<outboundRules>
    <!-- This rule changes the domain in the HTTP location header for redirection responses -->
    <rule name="Change Location Header">
        <match serverVariable="RESPONSE_LOCATION" pattern="^http://[^/]+/(.*)" />
        <conditions>
            <add input="{RESPONSE_STATUS}" pattern="^301" />
        </conditions>
        <action type="Rewrite" value="http://{HTTP_HOST}/{R:1}"/>
    </rule>
</outboundRules>

我明明感觉应该是302啊,这里为什么是301;还有Rewrite 里那么写真的对吗?我不确定,不过也得到一个思路使用RESPONSE_STATUS变量。

微服务、nodejs好像很火的样子,我也在尝试。希望这篇文章可以让node+nginx实现域名解析的人们多一种解决思路 node+iis+arr实现域名解析。

 


2018年4月11日更新:

有朋友用Nextcloud+ONLYOFFICE Document Server做了个文档管理云盘系统,通过IIS的反向代理访问,出现了资源链接未替换的错误。他最后找到一种只配置入站规则就可以实现全域名替换的方案,经测试可用。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="INIT_SERVER_VARIABLE_FROM_PROXY" stopProcessing="false">
          <match url=".*" /> 
          <serverVariables>          
            <set name="HTTP_THE_SCHEME" value="{HTTP_X_FORWARDED_PROTO}" replace="true" />            
            <set name="HTTP_THE_HOST" value="{HTTP_X_FORWARDED_HOST}" replace="true" />
          </serverVariables>
          <action type="None" />
        </rule>    
        <rule name="INIT_SERVER_VARIABLE_DEFAULT" stopProcessing="false">
          <match url=".*" /> 
          <conditions trackAllCaptures="true">
            <add input="{HTTPS}s" pattern="on(s)|offs" />
          </conditions>
          <serverVariables>          
             <set name="HTTP_THE_SCHEME" value="http{C:1}" replace="false" />            
             <set name="HTTP_THE_HOST" value="{HTTP_HOST}" replace="false" />                        
          </serverVariables>
          <action type="None" />
        </rule>    
        <rule name="DocumentServerRewrite" enabled="true">
          <match url="^documentserver-virtual-path(.*)" />
            <conditions trackAllCaptures="true">
              <add input="{HTTPS}s" pattern="on(s)|offs" />
            </conditions>
            <serverVariables>              
              <set name="HTTP_X_FORWARDED_PROTO" value="{HTTP_THE_SCHEME}" replace="true" />
              <set name="HTTP_X_FORWARDED_HOST" value="{HTTP_THE_HOST}/documentserver-virtual-path" replace="true" />
            </serverVariables>
            <action type="Rewrite" url="http://docservice{R:1}" />
         </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>
web.config

 

  

开博第一篇,推荐、推荐、推荐 一下吧,重要的事情说三遍。

  

 

posted @ 2016-03-12 17:54  Zeroes  阅读(3262)  评论(1编辑  收藏  举报