上下文:Azure、Windows Server 2012 R2、IIS 8
IIS 8 中的标准重写提供程序是
{
和 '}',它们在各种上下文中用于表示捕获、替换和符号,例如{C:0}
、{R:1}
、{HTTP_ORIGIN}
。
我正在尝试使用规则将 Google 跟踪代码管理器标记注入到页面中。
<rule name="Inject GTM After HEAD" preCondition="ResponseIsHtml1" enabled="true">
<match filterByTags="None" pattern="<head.*?>" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true" />
<action type="Rewrite" value="{R:0}<!-- Google Tag Manager --> <script>(function(w,d,s,l,i) { w[l]=w[l]||[];w[l].push( { 'gtm.start': new Date().getTime(),event:'gtm.js' } );var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); } )(window,document,'script','dataLayer','GTM-XXXX');</script> <!-- End Google Tag Manager -->" />
</rule>
这确实NOT工作,因为JavaScript包含
{
并且IIS的UrlRewrite工具立即抱怨黄色框显示The rewrite provider " w[l]=w[l]||[];w[l].push( { 'gtm.start'" does not exist
(请注意,它终止于:
,这将分隔通常的R
或C
)来自数字限定符。)
我尝试将
{
与 {
交换,但这效果不佳,在生成的网页中给出以下内容:
<!DOCTYPE HTML>
<html lang="en">
<head><!-- Google Tag Manager --> <script>(function(w,d,s,l,i) { w[l]=w[l]||[];w[l].push( { 'gtm.start': new Date().getTime(),event:'gtm.js' } );var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); } )(window,document,'script','dataLayer','GTM-XXXX');</script> <!-- End Google Tag Manager -->
<meta charset="UTF-8"/>
浏览器自然会抱怨 JavaScript 代码不可靠。
IIS 已经存在很长时间了。我希望解决方案对某人来说是显而易见的。通常需要做什么才能包含 JavaScript?
稍后
有人建议我用“注入”一词进行谷歌搜索。很酷的主意。结果?
我会附加一个查询字符串,并在重定向到的页面上有条件地包含你想要的 JS。
所以,你会得到类似的东西(来自这里)
<rewrite>
<rules>
<rule name="Redirect for download result page" stopProcessing="true">
<match url="(.*)/test.aspx(.*)" />
<action type="Redirect" url="{R:1}/test.aspx?rf=sp" appendQueryString="true" redirectType="Found" />
<conditions>
<add input="{QUERY_STRING}" pattern="flag=value" negate="true" />
</conditions>
</rule>
</rules>
</rewrite>
然后,在重定向的页面中,有类似这样的内容(来自here和here)
<script type="text/javascript">
if (window.location.href.indexOf("flag=value") > -1)) {
document.getElementsByTagName("head")[0].innerHTML += ("<script src=\"...\" type=\"text/javascript\"></script>");
}
</script>
我已记录了我在 DEV 使用的程序。
本质上,我们将 GTM 代码放在不同子域的 js 文件中,并嵌入一个带有指向该 js 文件的 src 的脚本标签。
是对脚本主体进行 URI 编码的更简单更通用的解决方案
例如
执行任意脚本,例如
(function(){console.log("hello");})()
获取编码版本...
encodeURIComponent("(function(){console.log(\"hello\");})()")
(请注意,我已经在脚本中对
"
进行了转义,必然在 encodeURI
的字符串参数中)
上面的输出是
'(function()%7Bconsole.log(%22hello%22);%7D)()'
请注意,此版本中没有
{
或 }
我们现在可以将脚本传递到重写规则中,例如......
eval(decodeURIComponent('(function()%7Bconsole.log(%22hello%22)%3B%7D)()'))
显然这是使用“可怕的”
eval
- 然而,由于我们完全控制(在服务器本身上)并传递我们选择的静态字符串 - 我相信这是 eval
的有效使用解决方法。
此解决方案不需要在其他地方托管任何
js
文件等。
我认为这也会编码/解码
:
s