【问题标题】:Dynamic inclusion of javascript in SVG by means of server side filtering inside apache server通过 apache 服务器内的服务器端过滤在 SVG 中动态包含 javascript
【发布时间】:2015-06-17 16:12:54
【问题描述】:

几年前,我编写了一些代码来自动在由 http 服务器提供的 html 页面中包含一些 javascript 代码。该方法记录在blog entryStackOverflow question 中。在过去的几年里,这个解决方案对我很有帮助。

两句话的方法:

  • 对于由 http 服务器提供的每个完整的 html 页面,一些占位符会通过服务器端替换添加到页面底部
  • 该占位符再次被替换为通过服务器端包含包含的 javascript 代码

现在我想扩展该解决方案并将相同的逻辑应用于基于 SVG 而不是 HTML 作为文档格式的页面。注意:不是 SVG 包含在 html 页面中,而是 SVG 格式的页面将被链接直接引用。

扩展本身不是问题,JavaScript 代码包含在 SVG 标记中。问题是代码没有被执行。不幸的是,我对 SVG 中的脚本编写知之甚少,这就是我有些迷茫的原因。也许有人可以给我一个提示这里出了什么问题:-)

各种 apache vhosts 定义中包含的过滤器链:

# ----------
# internal requests to include the piwik tracking code at the bottom of every html page

FilterDeclare PIWIK_token
FilterProvider PIWIK_token SUBSTITUTE resp=Content-Type $text/html
SUBSTITUTE 's|^\s*</body>|<!--#include virtual="/piwik"--></body>|iq'
FilterProvider PIWIK_token SUBSTITUTE resp=Content-Type $image/svg+xml
SUBSTITUTE 's|^\s*</svg>|<!--#include virtual="/piwik"--></svg>|iq'

FilterDeclare PIWIK_code
FilterProvider PIWIK_code INCLUDES resp=Content-Type $text/html
FilterProvider PIWIK_code INCLUDES resp=Content-Type $image/svg+xml

FilterChain PIWIK_token PIWIK_code

# map virtual request to the file system
Alias /piwik /srv/www/internal/piwik.php

# all that is left for the virtual host is to do two things:
#        SetEnv PIWIK_ID 15
#        Include /etc/apache2/vhosts.d/_internal.inc
# note: the '15' above is an example piwik site id

要包含的javascript代码是piwik tracking sn-p的略微修改版本:

<?php
define('piwikBase','https://some.domain.xxx/stats/');
define('piwikSite',apache_getenv('PIWIK_ID'));
if(is_numeric(piwikSite)){
?>

<script type="text/javascript">
  var _paq = _paq || [];
  _paq.push(["trackPageView"]);
  _paq.push(["enableLinkTracking"]);

  (function() {
    var u="<?= piwikBase ?>";
    _paq.push(["setTrackerUrl", u+"piwik.php"]);
    _paq.push(["setSiteId", "<?= piwikSite ?>"]);
    var d=document, g=d.createElement("script"), s=d.getElementsByTagName("script")[0]; g.type="text/javascript";
    g.defer=true; g.async=true; g.src=u+"piwik.js"; s.parentNode.insertBefore(g,s);
  })();
</script>

<?php } else { ?>
<!-- invalid piwik site id: <?php echo piwikSite;?> -->
<?php } ?>

如前所述:扩展工作正常,javascript 代码成功地包含在 SVG 文档中。但是它显然没有被激活,我没有看到它的原因......

最终交付的 SVG 如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:cc="http://creativecommons.org/ns#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    version="1.2"
    width="100%"
    height="100%"
    viewBox="0 0 640 400"
    docname="somedocument.svg">

[... content of the SVG ...]

<script type="text/javascript">
  var _paq = _paq || [];
  _paq.push(["trackPageView"]);
  _paq.push(["enableLinkTracking"]);

  (function() {
    var u="https://some.domain.xxx/stats/";
    _paq.push(["setTrackerUrl", u+"piwik.php"]);
    _paq.push(["setSiteId", "15"]);
    var d=document, g=d.createElement("script"), s=d.getElementsByTagName("script")[0]; g.type="text/javascript";
    g.defer=true; g.async=true; g.src=u+"piwik.js"; s.parentNode.insertBefore(g,s);
  })();
</script>

</svg>

【问题讨论】:

  • 问题似乎是 SVG 中动态创建和附加的 script 元素无法加载(?好吧……您的网络控制台说什么?)和/或未执行。这听起来很奇怪,因为似乎 [1] 在 HTML 嵌入的 SVG 从外部 中做同样的事情效果很好。 [1]stackoverflow.com/a/16626699/540955
  • @myf 不能在此处关注...从浏览器的角度来看,该脚本不是动态创建的。它是交付的文档的一部分。所以很明显它也不是以可能出现在网络控制台中的异步方式加载的,因为它已经包含在服务器端。
  • 啊,让我明确一点:script_paq.pushes 会创建新的 script 元素(请参阅 document.createElement('script') ?)和 appends 将它添加到您的 SVG 文档中,在它之前,作为 static originator(或如何调用它):您可以检查 DOM,您会在 SVG 中看到两个脚本。这就是我所说的动态创建。因此,您应该在网络控制台中看到 https://some.domain.xxx/stats/piwik.jsxlink:href(不是 src)。
  • 这最后一条评论让我知道出了什么问题,但问题一直存在,我只是没有发现它。很抱歉问了这些无关紧要的事情。

标签: javascript apache svg matomo


【解决方案1】:

只是猜测,但我会尝试更改代码,以便将动态脚本注入替换为带有xlink:href 的内联脚本标记(我已经测试过动态执行它,因为您的代码看起来“更正确”createAttibuteNS('xlink','href','...')但结果也没有执行)

生成的代码如下所示(尚未在真实环境中测试,因此请注意拼写错误):

<?php
define('piwikBase','https://some.domain.xxx/stats/');
define('piwikSite',apache_getenv('PIWIK_ID'));
if(is_numeric(piwikSite)){
?>
<script type="text/javascript"><![CDATA[
  var _paq = _paq || [];
  _paq.push(["trackPageView"]);
  _paq.push(["enableLinkTracking"]);
  _paq.push(["setTrackerUrl", "<?= piwikBase ?>piwik.php"]);
  _paq.push(["setSiteId", "<?= piwikSite ?>"]);    
]]></script>
<script type="text/javascript"
 xmlns:xlink="http://www.w3.org/1999/xlink"
 xlink:href="<?= piwikBase ?>piwik.js"
 defer="defer" async="async"></script>

<?php } else { ?>
<!-- invalid piwik site id: <?php echo piwikSite;?> -->
<?php } ?>

我不确定那些deferasync 的东西,它是否对SVG 有任何影响。我用简单的 datauri 样本对此进行了测试,它似乎运行良好。

注意事项:

  • 脚本上的xmlns:xlink="http://www.w3.org/1999/xlink" 或它的某些父级是必要的,但很可能你的 SVG 已经有了它
  • 在这种情况下,CDATA 不是必需的,但如果您计划在未来使用 &lt;&amp;……您知道吗。

【讨论】:

  • 嗯,不喜欢这意味着使用不同的javascript sn-ps。但也许它是必需的......我会试一试并报告。
  • 这行得通,谢谢!我修改了 apache 过滤器链以指向 html 和 svg 文档的两个单独的脚本版本。 html版本保持不变,svg版本按照你上面的建议。
【解决方案2】:

您不能使用

创建 SVG 脚本元素

g=d.createElement("脚本")

你需要写

g=d.createElementNS("http://www.w3.org/2000/svg", "script")

【讨论】:

  • 不幸的是,这并没有解决问题,同样的效果。不过还是谢谢!
猜你喜欢
  • 2012-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-04
  • 1970-01-01
  • 1970-01-01
  • 2022-10-17
  • 1970-01-01
相关资源
最近更新 更多