RewriteCond 适用于 HTTP 但不适用于 HTTPS 虚拟主机

RewriteCond works on HTTP but not on HTTPS virtual host

我想用尾随“.pdf”重写所有 URLs 以打开 mozilla.pdf.js 中的 pdf 文件,并在我的 HTTP 虚拟主机上成功测试遵循 RewriteRule 和 RewriteCond(我在 ubuntu 服务器上使用 apache2 btw):

要重写的示例 URL:

http://server-test.local/downloads/dir2/file5/test.pdf

示例目标 URL 重写后:

http://server-test.local/libs/mozilla.pdf.js/web/viewer.html?file=/downloads/dir2/file5/test.pdf
RewriteCond %{HTTP_REFERER} !viewer.html
RewriteRule ^(.+)(\.pdf)$ http://server-test.local/libs/mozilla.pdf.js/web/viewer.html?file= [R=301,L]

因此 RewriteCond 阻止了另一个重定向,这将导致 mozilla.pdf.js 尝试加载自身而不是 PDF 文件并导致错误。 (抱歉,如果描述不清楚,我不是很喜欢这个话题)

现在我尝试为我的其他虚拟主机 (https) 应用完全相同的 RewriteCond 和 RewriteRule,除了 SSL 和 Kerberos 实现之外,它与“服务器测试”虚拟主机完全相同:

RewriteCond %{HTTP_REFERER} !viewer.html
RewriteRule ^(.+)(\.pdf)$ https://server-prod.local/libs/mozilla.pdf.js/web/viewer.html?file= [R=301,L]

但似乎 RewriteCond 不适用。结果是,重定向到 mozilla.pdf.js 有效,但不会呈现 PDF 并且出现 mozilla.pdf.js 错误(“无效的 PDF 结构”),因为 - 这是我的理论 - 那里是另一个重定向,因此 mozilla.pdf.js 不会 load/render pdf,但它会尝试加载自己的 viewer.html

我也尝试了以下 RewriteConds,但没有一个改变了行为:

RewriteCond %{REQUEST_URI} !viewer.html*
RewriteCond %{REQUEST_URI} !^/libs/mozilla.pdf.js/web/viewer.html*
RewriteCond !viewer.html

我使用这些 RewriteCond 的目的是防止另一个(循环)重定向,如果 URL 在重写之前包含字符串“viewer.html”,那么如果 [...]/viewer.html?file=/downloads/dir2/file5/test.pdfREQUEST_URI,不应再发生重写。

有人可以向我解释一下,为什么 RewriteCond 可以在测试虚拟主机 (HTTP) 上运行,但不能在生产虚拟主机 (HTTPS) 上运行吗?除了 SSL 和 SSL 安全虚拟主机具有 Kerberos 实现这一事实外,虚拟主机、它们的目录和它们的配置大部分是相同的。是 SSL 的问题吗?有谁知道如何在 SSL 虚拟主机上解决这个问题?我需要以某种方式找到解决方案...

我会很感激每一种hints/help。

example target URL after rewrite: http://example.com/libs/mozilla.pdf.js/web/viewer.html?file=/downloads/dir2/file5/test.pdf

但是,您的指令当前不执行此操作。它 重定向 (不是“重写”)到 http://example.com/libs/mozilla.pdf.js/web/viewer.html?file=downloads/dir2/file5/test - 注意 file URL 参数值开头缺少的斜线和丢失的文件扩展。

如果在一台服务器上启用了 MultiViews,则这可能在一台服务器上运行,而在另一台服务器上则无法运行。 (这有效地使无扩展 URLs 能够“工作”。)

更正 RewriteRule 指令:

RewriteRule \.pdf$ https://example.com/libs/mozilla.pdf.js/web/viewer.html?file=%{REQUEST_URI} [R=301,L]

file URL 参数现在将包含 /downloads/dir2/file5/test.pdf

您需要在测试前清除浏览器缓存。但是,这应该是 301(永久)重定向吗?你在你的问题中提到“重写”并且你已经标记了问题 url-rewriting - 这不是。您是否希望将用户物理重定向到这个新 URL?看起来这真的应该是 内部重写 (即不公开 mozilla.pdf.js)?在这种情况下,应该像下面这样重写:

RewriteRule \.pdf$ /libs/mozilla.pdf.js/web/viewer.html?file=%{REQUEST_URI} [L]

an error of the mozilla.pdf.js appears ("invalid PDF structure"), because -thats my theory- there is another redirection, so the mozilla.pdf.js does not load/render the pdf but it tries to load its own viewer.html instead.

虽然如果是这种情况,那么它会导致 redirect-loop,但您看到的错误并不表示如此。

此外,您是否确认浏览器正在为此请求发送 Referer HTTP 请求 header 并且设置如预期?这里的问题是 Referer 不可靠 。出于多种原因,它可能会被浏览器抑制。

更好的方法是 mozilla.pdf.js 将自定义 header 设置为请求的一部分,并且可以在 mod_rewrite 条件.

或者,使 URL-path 不同于实际的文件系统路径。 (尽管如果 file-path 已知,则可以请求实际文件。)


旁白:

So the RewriteCond prevents another redirect which will cause the mozilla.pdf.js to try to load itself instead of the PDF file and cause an error.

它不会尝试加载“自身”。 RewriteRule 模式已经可以防止这种情况发生,因为它只匹配 .pdf 文件(尽管这不是这里发生的事情)。针对 Referer 的检查是为了防止递归循环...以防止 viewer.html 被重复调用并在 file [=79] 中传递相同的 .pdf 文件=] 参数.

我假设 mozilla.pdf.jsfile URL 参数中传递的 PDF 文件发出 HTTP 请求。 “问题”(在外部重定向的情况下)是区分来自用户的直接请求和来自 script 的请求(两者都是来自浏览器的客户端请求)。

我想,我可以通过另外添加

来解决我的问题

RewriteCond %{QUERY_STRING} !file=

到我的 RewriteRule 的 RewriteConds。现在 mozilla.pdf.js 打开并显示 PDF 文件。 @MrWhite 再次感谢您的解释。