如何让admin子域名的Laravel应用处理client子域名请求且保持浏览器URL不变
请求超出了10次内部重定向的次数限制,大概率存在配置错误。如有需要可通过调整
LimitInternalRecursion配置提高次数限制,设置LogLevel debug可获取回溯日志用于排查问题。
触发该报错的核心原因有两个:
- 移除替换路径的
https://前缀后,admin.mysite.com/bu/$1/$2会被Apache在.htaccess目录上下文下解析为当前站点下的相对路径,生成的新URI为/admin.mysite.com/bu/xxx,这个新URI会再次进入重写引擎流程,和原规则^/?([a-zA-Z][a-zA-Z0-9]*)/?(.*)$持续匹配,形成无限循环直到触发次数阈值报错。 - 之前尝试用
[P]代理标志不生效的原因:该标志依赖mod_proxy、mod_proxy_http模块启用,共享主机出于安全考虑通常会默认关闭这类代理模块;且[P]要求替换目标必须是带完整协议头的绝对URL,否则会被Apache当成普通内部重写处理。
实现地址栏不变的目标修复配置
不需要依赖代理模块,直接通过内部绝对路径重写即可实现无跳转的请求转发,修改client站点下的.htaccess配置如下:
<IfModule mod_rewrite.c> RewriteEngine on # 拦截已经进入/bu路径的请求,防止重写循环 RewriteCond %{REQUEST_URI} !^/bu/ # 内部重写到应用对应的路由路径,不触发外部跳转 RewriteRule ^/?([a-zA-Z0-9-]+)/?(.*)$ /bu/$1/$2 [L,NC] </IfModule>
配置生效后,所有指向client.mysite.com的请求会在服务器内部被路由到Laravel应用对应/bu路径的业务逻辑,浏览器地址栏全程保持原域名地址不变,也不会触发循环报错。
“通过Web服务器重写把子域名请求路由到同一套Laravel应用”的核心思路没有架构层面的问题,原有配置的缺陷只在细节实现上:
- 完全没有必要引入代理流程:两个子域名部署在同一台服务器、同一套Laravel代码上,内部路径重写的性能远高于跨应用代理转发,也不存在代理带来的请求头丢失、连接超时等常见问题。
- 之前遇到的循环报错属于Apache重写的常见配置错误,只要加了路径拦截条件就可以解决,不需要调整服务器底层的重写次数限制参数。
只要使用Apache内部重写规则(非外部301/302跳转),所有HTTP请求方法(GET/POST/PUT/DELETE、multipart格式的文件上传等)的请求头、请求体、参数都会被完整传递给后端Laravel应用,不存在兼容性问题。
只有当配置中出现带https://前缀的替换路径时,才会触发301/302类外部跳转,此时POST等请求的参数会被丢失、请求方法会被自动转为GET,这也是之前配置出现地址栏跳转的核心原因。
共享主机通常不允许修改底层Apache配置、默认关闭了代理模块,最适配的落地方案完全不需要依赖复杂的.htaccess重写逻辑:
- 在主机面板中将
client.mysite.com的站点根目录,直接指向和admin.mysite.com完全相同的Laravelpublic目录,不需要为client子域名单独部署一份独立代码。 - 在Laravel路由配置中增加多子域名路由解析:
- 原有admin子域名下的业务路由,用
Route::domain('admin.mysite.com')做路由分组 - client子域名下的对应业务路由,用
Route::domain('client.mysite.com')做路由分组,直接映射到和admin端相同的控制器逻辑
- 原有admin子域名下的业务路由,用
- 该方案的实际优势:
- 无重写循环风险,不需要写复杂的Apache规则,后期维护成本最低
- 性能最高,请求直接进入Laravel入口,无额外的Web服务器重写开销
- 完全适配共享主机的权限限制,只要主机面板支持子域名目录绑定即可实现,不需要申请修改任何系统底层配置
如果主机面板因配置限制,不支持将两个子域名绑定到同一个public目录,再使用前面提到的带循环拦截的内部重写规则即可,不需要启用代理模块,也不需要调整服务器的重写次数阈值参数。
内容的提问来源于stack exchange,提问作者goodUser

