Apache 文档指出 RewriteRule 和 应该放在服务器配置中,但由于共享主机情况,它们可以放在 htaccess 中。我就是这种情况。
我正在尝试设置透明代理:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/foo [OR]
RewriteCond %{REQUEST_URI} ^/bar
RewriteRule ^(.*)$ http://example.com/$1 [P]
这工作正常......除了重定向(比如如果
/foo
重定向到/bar
)。重定向返回到 example.com,而不是我的服务器。
我知道
ProxyPassReverse
指令会解决这个问题,但是当我将它添加到 .htaccess
时,我得到一个“内部服务器错误”页面
ProxyPassReverse
在 htaccess 中不起作用.
如何在共享主机情况下设置透明代理,或者这是不可能的?
(这似乎是合理的,因为 Rewrite 已经完成了 80%,并且在一个 htaccess 中拥有透明代理不会干扰在另一个 htaccess 中拥有它。)
不幸的是,我很确定你想做的事情是不可能的:我正在尝试做同样的事情!根据我的研究,我相当有信心这是不可能的。
简而言之,您需要使用 ProxyPassReverse,它仅在 VirtualHost 级别(或类似级别)可用;不是 htaccess 级别。
编辑:我实现此目的的唯一方法是还配置响应服务器/应用程序以知道它在代理后面,并适当地提供页面。也就是说,我使用 .htaccess 重定向到另一台服务器,如下所示:
RewriteEngine on
RewriteRule (.*) http://localhost:8080/$1 [P,L]
然后在应用程序服务器上——在本例中为 JIRA 安装——我适当地配置了 Java Tomcat/Catalina 以提供具有代理信息的页面:
proxyName="my.public.address.com"
proxyPort="80"
然而,这并不是完全透明的;应用程序服务器需要以代理方式提供页面。不过,它可能会有一些用处。
我设法收集了一些资源来弄清楚如何做到这一点。我使用共享托管服务提供商,因此我无权访问服务器配置 (httpd.conf)。我只能使用 .htaccess 来完成代理。这个例子是针对一个 WordPress 网站的,我希望其中的大部分内容由 origin.example.com 提供,但会有一些页面在本地提供,有点像覆盖。你可以走另一条路,只使用不同的 RewriteCond 规则代理特定的子目录。
须知:
我想要的:
我想调用 proxy.example.com 来提供内容 origin.example.com。就我而言,除了少数例外,我想映射所有内容。如果您只想映射网站的一部分,请相应地调整规则。
怎么做:
# I force everything coming into proxy.example.com to be HTTPS <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTP:X-Forwarded-Proto} !https RewriteCond %{HTTPS} off RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] </IfModule> <IfModule mod_proxy.c> # Redirect access for / (or any index) to the origin. NOTE target is http:// without SSLProxyEngine RewriteCond %{ENV:REDIRECT_STATUS} ^$ RewriteRule ^(index\.(php|html|cgi))?$ http://origin.example.com/ [P] # Do NOT redirect these patterns RewriteCond %{REQUEST_URI} !^/wp-admin/ RewriteCond %{REQUEST_URI} !^/wp-login.php RewriteCond %{REQUEST_URI} !^/programs/ # Redirect everything else. NOTE target is http:// without SSLProxyEngine RewriteCond %{ENV:REDIRECT_STATUS} ^$ RewriteRule ^(.+)$ "http://origin.example.com/$1" [P] # Mimic ProxyPassReverse. Fix the headers. Force to be https. Header edit Location ^https?://origin\.example\.com/(.*)$ https://proxy.example.com/$1 Header edit* Link https?://origin\.example\.com/ https://proxy.example.com/ </IfModule>
从 WordPress 过滤器中窃取以修改最终的 html 输出
2a) 添加必须使用的插件以添加“final_output”挂钩。在 wp-content/mu-plugins/buffer.php 添加一个文件:
<?php /** * Output Buffering * * Buffers the entire WP process, capturing the final output for manipulation. */ ob_start(); add_action('shutdown', function() { $final = ''; // We'll need to get the number of ob levels we're in, so that we can iterate over each, collecting // that buffer's output into the final output. $levels = ob_get_level(); for ($i = 0; $i < $levels; $i++) { // NOTE: Use only one of the two lines below // that has your output come out in the correct order. //$final .= ob_get_clean(); $final = ob_get_clean() . $final; } // Apply any filters to the final output echo apply_filters('final_output', $final); }, 0); ?>
2b) 将以下 PHP 添加到 wp-content/themes/yourthemenamehere/functions.php。它使用上面的“final_output”挂钩。 (使用匿名函数需要 PHP 5.3 或更高版本。)
add_filter('final_output', function($output) { // IP of the proxy server $WWW_IP = “4.4.4.4”; //$WWW_IP = “4.4.2.2”; // My workstation, for testing purpose only if ($_SERVER['REMOTE_ADDR'] == $WWW_IP) { // Force HTTPS when rewriting $output = str_replace('http://origin.example.com', 'https://proxy.example.com’, $output); // Catch anything that wasn’t a URL return str_replace(‘origin.example.com, 'proxy.example.com', $output); } return $output; });
如果一切顺利,您现在应该可以看到来自 origin.example.com 的内容由 proxy.example.com 提供。
我还在测试这个,所以如果你发现错误或遗漏,请添加评论。