Apache httpd 最近的一些问题录以及解决方法

http_response_code 的困惑

相同问题也在StackOverflow自问自答了。

在使用php-fpm 和 httpd 的时候我发现了个奇怪的现象。

如下面的例子。

1
2
3
4
<?php
$result = http_response_code(200);
var_dump($result);
phpinfo();

当设置response为200的时候,什么问题也没有,访问这个扔在web根目录的php文件,会成功在页面上输出dump的内容以及phpinfo的内容。但是,当我们把200改成400的时候,就出现了httpd自带的400页面。

这种现象给人产生一种错觉,那就是这个页面执行到http_response_code(400) 就中断了。因为同样尝试在非php-fpm的配置下执行相同的php脚本,是可以看到dump输入400的内容以及phpinfo的。

解决这个问题的关键是,你确定改脚本执行到http_response_code(400)就中断了吗?因为没有输出在页面上,所以很容易就产生了脚本中断的错觉。

验证这个错觉的方式很简单,把var_dump 改成向某个文件里面输入一些内容就行了。实验也证明的确文件中存在着我们输出的内容。

那么其实httpd做的事情就很明显了。

当我们返回非正常状态的时候(4xx,5xx) httpd匹配了类似下面的配置。

1
2
3
ErrorDocument 403 /error.html
ErrorDocument 404 /error.html
ErrorDocument 500 /error.html

那要如何取消这种默认的匹配而让我们的脚本来处理这种错误呢? 在config里面赫然发现了ProxyErrorOverride on 这个设定。把on设置称off。相当于告诉httpd 我们php-fpm的错误状态还是交给php-fpm来处理。

ProxyPass and ProxyPassReverse

在httpd中设置反向代理的时候我们常看到下面两行配置。

1
2
3
4
5
6
<VirtualHost myhost:80>
ServerName myhost
DocumentRoot /path/to/myapp/public
ProxyPass /app https://myapp:8080/
ProxyPassReverse /app https://myapp:8080/
</VirtualHost>

既然使用了ProxyPass ,那为啥要有ProxyPassReverse呢?

ProxyPassReverse是用来改写后端返回结果的header的。

当有如下302的跳转

1
https://myapp:8080/ => https://myapp:8080/new

我们服务器发送 /app 实际的导向会变成 /new, 而正确的导向应该是/app/new

所以ProxyPassReverse起到了查看后端返回的header,把里面的东西反过来加上/app