php的header()方法一般被用来告知浏览器做一些什么样的操作,比如跳转,刷新等等;而调用header方法前,如果使用echo输出一些内容,会发生什么情况呢?会对header函数有影响吗?我们实验来看看情况。
第一部分: 选择环境和版本
我们的测试选择的是LNNP,php的版本是5.3.8,相对较老的版本
第二部分:测试用例
<?php $str = "qwertyuiopasdfghjklzxcvbnm1234567890~!@#$%^&*()_+"; $time = 10; for ($i = 0; $i < $time; $i ++){ $x = rand(0, 40); $v = substr($str, $x, 1); echo $v; } header(‘Refresh:3, http://www.baidu.com‘);
解释一下这个测试用例,
1、$time变量用来控制echo输出字符的大小
2、为什么用for循环输出乱序的字符?原因从第三部分抓包的情况可以看到,浏览器端一般要求response内容部分进行gzip压缩。而这个压缩实际上是php做的,为排除gzip压缩对实验影响,所以用for循环做乱序输出
第三部分:抓包分析
1、正常情况,$time变量比较小的情况下
1) 浏览器发送请求给Nginx
2) nginx将请求包装后发送给php-fpm
3) php-fpm将结果回传nginx
4) nginx将结果回传浏览器
2、异常情况,$time变量较大的情况下
我们看1中第三步,php-fpm将结果回传nginx,我们发现两点
1) 无法实现跳转。 从抓包的情况是php无法修改输出header头的信息,其原因应该是header信息,已经被write到socket fd中,缓存池中不存在header信息,所以无法修改
2) echo输出的内容无影响。
第四部分:分析和结论
结合上面的情况,从第三部分的第一点,我们实际上可以看出,header函数的实现,实际上是把header函数的参数,作为字符串加到输出的返回内容 的header头部分,而在echo内容较大的时候,header头的字符串就无法输出了。
我们可以看出php的处理过程 echo 的内容都会被放到缓存池内,当缓存池满的时候, 会将缓存池的内容write到socket fd内,一旦write进去,header函数将无法再把header字符串写到返回请求的header头部分。所以这种情况下,header函数将失效。