最后是时候将 JavaScript 应用于特定网站了,因此我编写了一些在测试子目录中运行良好的代码,但当我将其部署到网站时却遇到了问题。当我尝试使用不在目录或调用它的页面所在子目录中的脚本文件时,似乎会出现问题。这将是一个大问题,因为新功能是整个网站都需要的,并且目录结构会根据我们不需要在此处讨论的其他机制动态变化;调用顶级脚本的能力至关重要。
因此,我将其全部精简为两行非常简单的 JavaScript,以帮助阐明问题;当它包含在调用 html 所在目录中的文件中时,它可以工作,或者包含在该目录中的子目录中,或者如果我通过指向另一个位置的链接在同一目录中引用它,那也没问题。但是,如果我尝试以任何其他方式引用脚本文件,它会失败,并显示:
[2016 年 12 月 8 日星期四 12:08:26.643037] [cgi:error] [pid 27403] [客户端 xx.xx.xx.xx:46247] AH01215:(8)Exec 格式错误:'/usr/www/http/js/test.js' 执行失败,引用者:http://example.com/test/jstest.html[2016 年 12 月 8 日星期四 12:08:26.643548] [cgi:error] [pid 27403] [客户端 xx.xx.xx.xx:46247] 脚本输出在标头之前结束:test.js,referer:http://example.com/test/jstest.html
这里,xx.xx.xx.xx 当然是服务器的 IP,“example.com”是所讨论的域,路径“/usr/www/http”是 Apache 为该域的网站提供服务的顶级目录。
我已经阅读了很多关于这方面的材料,我知道 Apache 配置文件很重要...我尝试设置 ScriptAlias 并且对此有几个疑问,我似乎无法找到清楚的答案:
- HTML 代码中如何引用“ScriptAlias”目录中的脚本 - 以斜线开头?是否有一些特殊字符表示“网站顶部”?以及;
- 整个站点是否只允许有一个唯一的 ScriptAlias 目录,或者是否可以有多个可供搜索的目录 - 如果是这样,如何指定它们、ScriptAlias 的多个定义、逗号分隔列表等?以及;
- 我们可以为每个 VirtualHost 设置一个吗?我们可以通过在 Virtual Host 定义中放置一个 ScriptAlias 来实现吗?
为了使测试更容易一些,我在不同目录中同名的文件中创建了几乎相同代码的多个实例,并稍微改变了内容,这样我就可以轻松确定哪个位置对哪种调用产生了影响,同时查看 Apache 日志。以下是其中一个文件的示例:
var myHeading = document.querySelector('h2');
myHeading.textContent = 'website top level js dir';
textContent
此代码采用第一个标签,并将内容替换为第二行提供的内容。显然,我正在更改以textContent
匹配位置。
在 HTML 中,只要调用页面与 test.js 位于同一目录或父目录中,或者存在指向 test.js 的链接(该链接位于同一目录或子目录中),任何类似以下的引用都可以起作用:
<script src="test.js"></script>
<script src="js/test.js"></script>
<script src="http://example.com/test/js/test.js"></script>
在 HTML 中,只要调用 html 不在同一目录或父目录中,无论我尝试什么,任何类似这样的引用都会失败:
<script src="/js/test.js"></script>
<script src="/usr/WWW/http/js/test.js></script>
<script src="http://example.com/test/js/test.js"></script>
涉及的目录和文件都是属于我个人的UID和GID(一直以来都是),并且它们的权限都是755。
有一个全局的 ScriptAlias 定义为(也尝试了其变体):
ScriptAlias /js/ "/usr/www/js/"
虚拟主机定义中还有另一个 ScriptAlias 条目 - 不知道它是否有用!据我所知,没有任何效果。... 而且,我尝试过的所有目录的主配置文件中都有这样的目录条目:
<Directory /usr/www/http/js/>
AllowOverride None
Options ExecCGI
Require all granted
</Directory>
更新 弗雷迪想要一棵树。很好:
该树从虚拟主机的文档根目录开始 - 谁在乎在哪里?从那里开始:
├── index.html
├── js
│ └── test.js
└── test
├── js
│ └── test.js
└── testjs.html
3 directories, 4 files
答案1
这不ScriptAlias
符合预期。您不能将客户端 JavaScript 文件放在ScriptAlias
指令中描述的目录中。
ScriptAlias
是 Apache 配置指令,指示它尝试将该目录中的文件作为程序执行并返回程序的输出,而不是简单地将静态文件传输给用户代理。这显然不是您想要的。这是浏览器应该运行 JavaScript,而不是服务器。
答案2
首先,我从你的问题中注意到了一些事情:
- ScriptAlias 与客户端脚本无关,它用于服务器端脚本/CGI
文件系统执行标志对客户端脚本无关紧要
在此代码片段中:
<script src="/usr/WWW/http/js/test.js></script>
我觉得你在那里输入了完整的文件系统路径,你应该使用 URI 路径,注意区别。读作 URI 路径,它假设可以从以下位置下载脚本:
http(s)://example.com/usr/WWW/http/js/test.js
实际上,从您的日志中我看到的情况是,Apache 正尝试将 javascript 传递给 CGI 进程但失败了,实际上它是一个客户端脚本:
[2016 年 12 月 8 日星期四 12:08:26.643037] [cgi:error] [pid 27403] [客户端 xx.xx.xx.xx:46247] AH01215:(8)Exec 格式错误:'/usr/www/http/js/test.js' 执行失败,引用者:http://example.com/test/jstest.html[2016 年 12 月 8 日星期四 12:08:26.643548] [cgi:error] [pid 27403] [客户端 xx.xx.xx.xx:46247] 脚本输出在标头之前结束:test.js,referer:http://example.com/test/jstest.html
因此,首先将您的 javascript 移到 ScriptAlias 路径之外。同时,您可以tree
在文档根目录上运行,您可以省略文件,只需保留包含 javascript 的 html 文件和 javascript 本身,这样我们就可以更好地了解情况。
树输出后更新
假设加载 javascript 的 html 页面是文档根目录中的 index.html,则加载第一个 javascript 的正确方法(下面的方法$DOC_ROOT/js/test.js
是):
<script src="/js/test.js"></script>
如果你想加载第二个,即“测试”树下的那个:
<script src="/test/js/test.js"></script>
那就是文件系统 小路 $DOCUMENT_ROOT
被翻译成 _URI小路'/',或 http(s)://example.com/
如果一切不顺利,请检查您的日志。如果您收到上述 AH01215 错误,请再次检查您的 ScriptAlias 设置(我知道您这样做了,但该错误与此有关)