【发布时间】:2010-12-22 09:17:52
【问题描述】:
我之前问过这个问题,但又遇到了问题,无法解决。我有一个内部代理服务器和一个内容服务器。代理服务器上的代码是这样的。 (有些 cmets 可能是错的,但留下来表达我的理解):
<?php
session_start();
$data_server_url = "http://my_data_server_url/";
$i_var_prefix="i_var_";
$process_headers_separately=0;
//$process_headers_separately=1;
// WARNING! Has problems with GZIPPED DATA!
// AVOID/REMOVE OPTION ALLTOGETHER
// (Set to 1 if you want to catch received headers
// and send explicit headers to clients)
//-----------------------------------------
// Other important request dependent 'SERVER' variables.
if(isset($_SERVER['HTTPS']))
{ $_POST["${i_var_prefix}_HTTPS"]=$_SERVER['HTTPS']; };
if(isset($_SERVER['REMOTE_ADDR']))
{ $_POST["${i_var_prefix}_REMOTE_ADDR"]=$_SERVER['REMOTE_ADDR']; };
$request_uri="";
if(isset($_SERVER['REQUEST_URI'])) { $request_uri = $_SERVER['REQUEST_URI']; };
$curl_url="${data_server_url}${request_uri}";
$field_array= array(
'Accept' => 'HTTP_ACCEPT',
'Accept-Charset' => 'HTTP_ACCEPT_CHARSET',
'Accept-Encoding' => 'HTTP_ACCEPT_ENCODING',
'Accept-Language' => 'HTTP_ACCEPT_LANGUAGE',
'Connection' => 'HTTP_CONNECTION',
'Host' => 'HTTP_HOST',
'Referer' => 'HTTP_REFERER',
'User-Agent' => 'HTTP_USER_AGENT'
);
$curl_request_headers=array();
foreach ($field_array as $key => $value) {
if(isset($_SERVER["$value"])) {
$server_value=$_SERVER["$value"];
$curl_request_headers[]="$key: $server_value";
}
};
//------
session_write_close();
//Open connection
$curl_handle = curl_init();
curl_setopt($curl_handle,CURLOPT_COOKIE,session_name()."=".session_id().";");
//Set the url, number of POST vars, POST data
curl_setopt($curl_handle, CURLOPT_URL, $curl_url);
curl_setopt($curl_handle, CURLOPT_POST, count($_POST));
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $_POST);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_AUTOREFERER, TRUE);
curl_setopt($curl_handle, CURLOPT_HEADER, $process_headers_separately);
curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $curl_request_headers);
curl_setopt($curl_handle, CURLOPT_ENCODING, "identity");
//Execute post
$result = curl_exec($curl_handle);
//Close connection
curl_close($curl_handle);
if ($process_headers_separately) {
list($headers,$content)=explode("\r\n\r\n",$result,2);
foreach (explode("\r\n",$headers) as $hdr) {
header($hdr);
}
echo $content;
} else {
echo $result;
}
?>
问题一: 以目前的代码,即使data_server返回的Content-Type是text/plain,客户端看到的content-type也是text/html。 例如,见http://sarcastic-quotes.com/robots.txt 这个请求转到上面的文件。我已经检查了 data server 实际上将 Content-Type 作为 text/plain 返回。但是通过代理,客户端将响应标头中的内容类型视为 text/html。
问题2:注意变量process_headers_separately的使用。如果我将它设置为 1,那么浏览器会尝试下载 gzip 文件而不是显示内容(无论数据服务器返回什么内容类型)。因此,该代码流中存在一些逻辑错误。
我只是想让上面的代码作为一个内部代理,无缝地充当我的数据服务器和客户端之间的桥梁。任何想法都将不胜感激,我真的很困惑如何正确处理上面的标题。
问候, JP
当process_headers_separately=1(浏览器下载文件而不是显示)时,我找到了问题的原因。但这太奇怪了,我无法解决。问题:如果我取消注释行 if(isset($_SERVER['REMOTE_ADDR'])) { $_POST["${i_var_prefix}_REMOTE_ADDR"]=$_SERVER['REMOTE_ADDR']; };
然后事情开始正常了!奇怪的!
这一定是像 Neil 建议的一些疯狂的空白问题。
无论如何,尝试解决这个问题 - 由于这个疯狂的错误,我已经花了 3 天(之前 2 天,现在 1 天):(。感谢 Neil 和 RF 在这方面的帮助。
【问题讨论】:
-
RabidFire 的 curl_getinfo 方法至少可以正确传输内容类型。但是,我正在尝试“全部接力”方法。在那,无论我尝试什么,浏览器总是试图下载文件。代理服务器似乎再次压缩了整个标题和内容,并且正在发生某种双重压缩。如果我解压缩下载的文件,则解压缩文件的标题为可读文本,实际页面内容为 gzip 压缩数据。
-
如果您的浏览器正在尝试下载文件,那么您的
Content-Type标头设置为浏览器无法显示的内容,例如application/octet-stream,或者Content-Disposition标头设置不正确。未解压缩的压缩数据,带有正确的标题,至少应该只显示 gobbledegook。 -
您能否编辑问题以反映您对代码所做的任何更改?我会再做一个小测验。
-
我已经放入了新代码,并结合了您和 RF 建议的更改。谢谢
-
确保来自 CURL 的
Content-Encoding响应标头与其实际提供的输出之间没有不匹配。如果 CURL 认为可以解压缩内容,它会尝试解压缩,因此您需要使用gzcompress()或gzdeflate()重新压缩它。除了压缩之外,您的内容类型问题还存在吗?另外,尝试用apache_request_headers()替换$curl_request_headers。有时,当您使用mod_rewrite时,您最终会得到像$_SERVER['HTTP_REDIRECT_ACCEPT_ENCODING']这样的东西,而不是您正在寻找的东西。
标签: php http curl content-type httpresponse