ThinkPHP从header请求头中获取数据信息下划线和中划线的区别

发布时间:2023-08-24浏览次数:640 次
今天在从thinkphp的请求头中,获取信息时,遇到点坑,这里记录一下,以便后续注意:通过前端发送数据请求时,header中添加了数据:instance.int

今天在从thinkphp的请求头中,获取信息时,遇到点坑,这里记录一下,以便后续注意:

通过前端发送数据请求时,header中添加了数据:

instance.interceptors.request.use(
    config => {
        config.headers.access_token = "1111";
        return config;
    }, error => {
        return Promise.reject(error)
    })

但是从后端,通过thinkphp接收数据时,总是接收不到。但是打印$request->header()却发现时存在access_token的。

$request->header(); // 存在access_token
$request->header('access_token'); // null

翻阅thinkphp官方文档,其中有这样一段描述:“HTTP请求头信息的名称不区分大小写,并且_会自动转换为-,所以下面的写法都是等效的”。

我们将这里换成:

$request->header('access-token'); // null

也依然还是获取不到,无奈,只好修改了前端向header中添加数据时的键名,改为:config.headers.access-token,则可以获取到。

问题本身解决起来并不复杂。然而我们希望探究一下,服务器为何要忽略掉字段名中使用了下划线的属性呢?

关于这快,TP官方并未说明,经查阅资料发现:http请求头header参数中含有下划线是不能被正常接收的。

在 RFC 2616 4.2 节中,有这样一段说明:

The  field-name must be composed of printable ASCII characters (i.e., characters that  have  values  between  33.  and  126., decimal, except colon).

也就是说:header字段名可以可由可打印的 ASCII 字符组成(也就是十进制值在 33 和 126 之间的字符,不含冒号)。

不含冒号很容易理解,因为 Field-Name和 Value之间需要用冒号分割。然而,我们通过查询 ASCII 码表可知,下划线的十进制 ASCII 值为 95,是在此范围之内! 因此上,在 header字段名中使用下划线其实是合法的、符合 HTTP 标准的,但,实际测试中,所有含下划线的字段,都接收不到。这是怎么回事呢?

服务器之所以要默认禁止使用是因为 CGI 历史遗留问题。下划线和中划线都为会被映射为 CGI 系统变量名中的下划线,这样容易引起混淆。 

在 nginx 服务器中,通过显式地设置

underscores_in_headers on

可以开启在字段名中使用下划线。默认该选项是关闭的,所以在默认情况下,所有包含下划线的字段名都会被丢弃。因此建议不要在 header的 Field-Name字段名中使用下划线。 

再回到我们的问题,因为TP框架有自动将下划线(_)改未中划线(-)的功能,因此,我们只需要在前端存储数据时注意,不要使用下划线(_)即可,在后端,我们依旧可以使用下划线(_)来接收。如下:

$access_token = $request->header('access-token'); // 这里可以使用 - 也开始使用_
$refresh_token = $request->header('refresh-token');

但是,为了统一期间,建议大家还是都才用中划线的写法,以便于代码维护。当然,php中的变量名,还是只能使用下划线。

扫一扫,在手机上查看