主域为反向代理时,如何将子域名重定向至主域子目录?
解决方案:基于现有技术栈实现blog域名重定向
核心问题分析
之前的方案失败原因很明确:
- 无限重定向:Flywheel的全局重定向会把所有
blog.example.com的请求转去www.example.com/blog/*,但后者又通过反向代理回源到blog.example.com,形成循环。 - CNAME未生效:单纯修改DNS记录只是把流量导向Heroku,但Heroku的RoR应用并没有配置接收
blog.example.com的请求,而且Flywheel仍然绑定了该域名,流量实际还是会落到Flywheel服务器。
可落地的实现步骤
1. 配置反向代理请求头(RoR端)
首先在RoR应用的rack-reverse-proxy配置中,添加一个自定义请求头,标记这是来自反向代理的请求。这样Flywheel端可以识别并跳过重定向逻辑。
在你的代理配置文件(比如config/initializers/rack_reverse_proxy.rb)中添加:
Rack::ReverseProxy.configure do reverse_proxy_options preserve_host: true reverse_proxy '/blog', 'https://blog.example.com', headers: { 'X-Proxy-Source' => 'Heroku' } end
preserve_host: true可以让Flywheel收到的请求Host头保持为www.example.com,辅助避免循环;自定义头则是更可靠的判断依据。
2. 在Flywheel端添加条件重定向
方式一:通过.htaccess规则(推荐)
在Flywheel的WordPress根目录下编辑.htaccess,添加带条件判断的301重定向规则:
RewriteEngine On # 仅对非反向代理的外部请求执行重定向 RewriteCond %{HTTP:X-Proxy-Source} !^Heroku$ RewriteCond %{HTTP_HOST} ^blog\.example\.com$ [NC] RewriteRule ^(.*)$ https://www.example.com/blog/$1 [R=301,L]
这条规则会跳过来自Heroku反向代理的请求,只重定向外部用户直接访问blog.example.com的流量,彻底打破循环。
方式二:通过WordPress代码实现
如果无法编辑.htaccess(比如Flywheel限制),可以在主题的functions.php中添加以下代码:
add_action('template_redirect', function() { // 判断是否是外部访问blog域名的请求 if ( isset($_SERVER['HTTP_HOST']) && strtolower($_SERVER['HTTP_HOST']) === 'blog.example.com' && !isset($_SERVER['HTTP_X_PROXY_SOURCE']) ) { $target_url = str_replace( 'blog.example.com', 'www.example.com/blog', home_url($_SERVER['REQUEST_URI']) ); wp_redirect($target_url, 301); exit; } });
3. 验证DNS与域名绑定
- 保留DNSSimple中
blog.example.com的A记录指向Flywheel IP(因为反向代理需要回源到Flywheel),不要改成CNAME,否则Heroku无法回源到正确的服务器。 - 确保Flywheel控制台中
blog.example.com的域名绑定仍然存在,否则反向代理会失败。
是否需要调整技术栈?
不需要。现有RoR+Flywheel+反向代理的架构完全可以满足需求,只需要通过条件重定向+自定义请求头的组合打破循环即可,无需引入新的技术或服务。
内容的提问来源于stack exchange,提问作者Aayush Kothari
相关产品推荐
相关产品推荐

