X-Accel-Redirect:原理剖析与实战应用
本文包含AI辅助创作内容
X-Accel-Redirect 是 Nginx 给后端程序留的一个内部跳转能力。Laravel 先接到请求,判断业务规则;如果这个请求应该交给 Nginx 处理,就返回一个内部 URI。
浏览器不会直接看到这个内部路径。Nginx 收到响应头后,会在自己内部重新匹配 location,再去读静态文件、代理 SSR 服务,或者输出受保护的下载文件。
一、它不是跳转
X-Accel-Redirect 不是 302。浏览器地址栏不会变,也不会再发一次公开请求。
X-Accel-Redirect: /__site_ssr/site
Laravel 返回的是 Nginx 内部 URI,不是完整 URL。后面的 proxy_pass、alias、try_files 都交给 Nginx 配置。
二、Laravel 里怎么返回
Laravel 可以返回一个空响应,只带响应头。
use Illuminate\Support\Facades\Response;
public function page()
{
// 这里先做业务判断:域名、权限、页面类型等。
if ($this->shouldUseStaticSite()) {
return Response::make('', 200, [
'X-Accel-Redirect' => '/__static_site/',
]);
}
return $this->renderPage();
}
内部路径最好统一拼,不要在控制器里到处写字符串。
private function buildAccelRedirectUri($path)
{
// 统一去掉多余斜杠,避免拼出 // 这种路径。
$path = '/' . ltrim($path, '/');
return '/__site_ssr' . $path;
}
状态码最好明确写 200。如果业务代码前面已经抛过异常,最后看到的可能还是 500。
三、Nginx 接静态目录
静态站点兜底可以这样配:
location = /__static_site/ {
internal;
alias /data/projects/static-site/dist/index.html;
default_type text/html;
}
location ^~ /__static_site/ {
internal;
alias /data/projects/static-site/dist/;
try_files $uri $uri/ /index.html;
}
internal 很关键。有了它,外部用户不能直接访问内部地址,只有后端返回 X-Accel-Redirect 时才会命中。
四、Nginx 接 SSR 服务
后面不是静态目录,而是 SSR 服务,也可以。
location ^~ /__site_ssr/ {
internal;
rewrite ^/__site_ssr/?(.*)$ /$1 break;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Request-Id $request_id;
proxy_pass http://site_ssr_backend;
}
rewrite 是为了把内部前缀去掉。否则 SSR 收到的是 /__site_ssr/site,而不是 /site。
五、root 和 alias 别混
如果内部路径只是虚拟前缀,真实文件在 dist 目录下,优先用 alias。
root:把 URI 拼到目录后面
alias:把 location 前缀映射到真实目录
location ^~ /__static_site/ {
internal;
alias /data/projects/static-site/dist/;
try_files $uri $uri/ /index.html;
}
六、500 怎么排
先确认有没有命中内部 location。可以临时加一个调试头。
location = /__static_site/ {
internal;
alias /data/projects/static-site/dist/index.html;
default_type text/html;
add_header X-Debug-Static exact always;
}
curl -k -I https://example.com/
如果响应里有这个头:
X-Debug-Static: exact
说明链路已经通了。接下来查文件是否存在、Nginx 权限、try_files 是否循环、Laravel 返回状态码是不是 200。
七、放在哪一层判断
有些判断不能放太晚。如果基类或中间件已经因为站点不存在抛了 404,具体 action 里的 X-Accel-Redirect 根本没机会执行。
请求进来
先判断是否需要内部转发
需要:返回 X-Accel-Redirect
不需要:继续原来的站点解析和页面渲染
八、最后
X-Accel-Redirect 的关键不是“转发”两个字,而是分工。
返回内部 URI,不返回完整 URL
Nginx location 要加 internal
静态目录优先用 alias
代理 SSR 时去掉内部前缀
状态码明确返回 200
500 先看 Nginx error log
老项目里想加一段新前端、新 SSR、新下载逻辑,又不想把原来的入口拆得太散,就使用这个方案解决。

请先 登录后发表评论 ~