应使用 $request->header() 方法读取请求头,它比直接访问 $_server 更安全、兼容,自动处理大小写、代理转发及空值;避免用 $request->headers->get() 或 request()->header(),中间件中须通过类型提示注入 $request。

如何在 Laravel 控制器中读取请求头信息
直接用 $request->header() 方法,它比手动访问 $_SERVER 更安全、更兼容。Laravel 会自动处理大小写不敏感匹配和代理转发场景(比如 Nginx 转发的 X-Forwarded-For)。
常见错误是写成 $request->headers->get('xxx') —— 这也能用,但绕过了 Laravel 的标准化封装,容易漏掉空值处理或大小写归一化逻辑。
-
$request->header('Authorization')返回字符串,若不存在则返回null;加默认值:$request->header('X-Api-Key', 'default-key') - 批量读取多个头:
$request->headers->all(),但注意返回的是二维数组(每个键对应一个值数组),实际常用$request->header('xxx')单取 - 如果头名含连字符(如
X-Requested-With),Laravel 会自动转为驼峰或下划线风格匹配,所以$request->header('x_requested_with')和$request->header('X-Requested-With')都能命中
Laravel 中间件里怎么获取请求头
中间件接收的 $request 对象和控制器里完全一致,照样用 $request->header()。但要注意:中间件执行时机早于控制器,某些头可能被后续中间件覆盖或删除(比如认证中间件清空 Authorization)。
典型误操作是试图在中间件里用 request()->header() 辅助函数——虽然能跑通,但依赖全局服务容器,不利于单元测试和可维护性;应始终通过参数注入的 $request 实例来读取。
- 在
handle()方法签名中确保已声明类型提示:public function handle($request, Closure $next),否则$request是原始Illuminate\Http\Request实例,但方法可用 - 调试时可临时加
Log::debug($request->headers->all());查看完整头列表,注意日志里Authorization等敏感字段会被 Laravel 自动脱敏 - 若需判断是否存在某头(不关心值),用
$request->hasHeader('X-App-Version')比!is_null($request->header('X-App-Version'))更语义清晰
为什么 $_SERVER['HTTP_X_CUSTOM_HEADER'] 有时读不到
PHP 默认会把请求头中的连字符转成下划线,并统一加 HTTP_ 前缀,但前提是 Web 服务器(Nginx/Apache)确实把该头透传给了 PHP。很多情况下是 Nginx 配置漏掉了 proxy_set_header,或者 Apache 启用了 mod_security 拦截了自定义头。
Laravel 的 $request->header() 底层仍依赖 $_SERVER,但它做了容错:会依次尝试 HTTP_ 前缀、REDIRECT_HTTP_(CGI 模式)、以及直接从原生 getallheaders()(CLI 或 FPM 下不一定可用)中提取,所以比直读 $_SERVER 更可靠。
- 检查 Nginx 是否透传:确认有类似
proxy_set_header X-Trace-ID $http_x_trace_id;的配置,且客户端真正发了该头 - Apache 用户注意:需开启
mod_headers,并在虚拟主机中用RequestHeader set X-Custom-Header "%{HTTP:X-Custom-Header}e"显式暴露 - 本地开发用
php artisan serve时,PHP 内置服务器不支持自定义头透传,必须改用 Valet / Docker / Nginx 环境验证
读取 Authorization 头的特殊注意事项
这个头最常用于 Bearer Token 或 Basic Auth,但 Laravel 的认证系统(如 Auth::guard('api')->user())已经内部调用了 $request->header('Authorization'),重复读取一般没必要。真要手动解析,得先剥离前缀再 Base64 解码。
常见坑是没处理空格分隔符,比如 Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...,直接 substr($token, 7) 不安全,因为前缀可能是 Bearer (带空格)或 bearer(小写)。
- 推荐用 Laravel 自带的解析方式:
$token = $request->bearerToken();—— 它会自动 trim、忽略大小写、提取空格后内容 - 如果是 Basic Auth,用
$request->server('PHP_AUTH_USER')和$request->server('PHP_AUTH_PW')更稳妥,因为 Apache/Nginx 已完成解码,避免自己处理 Base64 和冒号分割 - 别在日志里打印完整
Authorization头值,Laravel 默认会过滤,但若用Log::info(['auth' => $request->header('Authorization')])就会泄露 token
php artisan serve 时头透传不完整,而上线后 Nginx 配置又忘了加 proxy_set_header,导致自定义头在本地能取到、线上永远为 null。











