referer = "";
$hr->cookie = "";
$hr->timeOut = 30;
$hr->cacheSize = 2048;
$RESULT = $hr.action();
$RESULT 格式
Array (
头部信息
[HTTP/1.1] => 200 OK
[Content-Type] => text/plain
[Last-Modified] => Thu, 15 Jun 2017 04:34:27 GMT
[Accept-Ranges] => bytes
[ETag] => "cd8851ac90e5d21:0"
[Server] => Microsoft-IIS/7.5
[X-Powered-By] => ASP.NET
[Date] => Thu, 15 Jun 2017 06:49:41 GMT
[Connection] => close
[Content-Length] => 951
正文信息
[Document_Body] =>
错误信息
[error] =>
)
*/
class HttpRequest
{
/// 主机地址
private $host = "";
/// 协议传输方式 GET POST
private $method = "get";
/// 端口
private $port = 0;
/// 请求路径
private $path = "";
/// 请求参数
private $query = "";
/// POST方式要传输的数据
private $postData = null;
/// Cookie
Public $cookie = "";
/// Referer
Public $referer = "";
/// 连接超时
public $timeOut = 5;
/// 读取缓存大小
public $cacheSize = 2048;
/// 是否阻塞模式
public $blocked = TRUE;
///构造函数,根据参数数量选择对应方法
function __construct()
{
$a = func_get_args();
$i = func_num_args();
if (method_exists($this, $f="__construct".$i))
{
call_user_func_array(array($this,$f),$a);
}
}
/// 构造函数派生方法
private function __construct2($Url,$Method)
{
$this->parse_base_url($Url,$Method);
}
private function __construct3($Url,$Method,$PostData)
{
$this->parse_base_url($url,$method);
$this->$postData = !isset($PostData) ? $PostData : "";
}
/// URL地址解析
private function parse_base_url($u,$m)
{
$col = parse_url($u);
!isset($col["host"]) && $col["host"] = "";
!isset($col["path"]) && $col["path"] = "/";
!isset($col["query"]) && $col["query"] = "";
!isset($col["port"]) && $col["port"] = "";
$this->host = $col["host"];
$this->port = !empty($col["port"]) ? $col["port"] : 80;
$this->path = $col["path"];
if(array_key_exists("query",$col))
{
$this->query = !isset($col["query"])?$col["query"]:"";
}
$this->method = ($m === "post") ? $m : "get";
}
/// HTTP头部解析
private function parse_HTTP_Headers($headerStr)
{
$len = $pos = 0;
$str = $headerStr;
$reslt = array();
$split = strpos($str, "\r\n") > 0 ? "\r\n" : "\n";
$i = 1;
while($pos < strlen($str))
{
$key = $val = "";
$len = stripos($str, " ", $pos) - $pos;
$key = str_replace(":", "", substr($str, $pos, $len));
$pos += $len + 1;
$len = stripos($str, $split, $pos) - $pos;
$val = str_replace($split, "", substr($str, $pos, $len));
$pos += $len + 2;
$reslt[$key] = $val;
if(strlen($str) - $pos == 2) break;
}
return $reslt;
}
/// 产生请求包
protected function makeRequestStr()
{
$reqStr =($this->method === "get" ? "GET" : "POST")." ".$this->path.$this->query." HTTP/1.1 \r\n";
$reqStr .="Host: ".$this->host.":".$this->port."\r\n";
$reqStr .= "Accept: text/html,application/xhtml+xml,application/xml;image/webp,*/*\r\n";
$reqStr .= "Accept-Language: zh-CN,zh\r\n";
$reqStr .= "Accept-Encoding: gzip, deflate\r\n";
$reqStr .=(($this->method === "post") ? "Content-Type: application/x-www-form-urlencoded\r\n" : "");
$reqStr .="User-Agent: ".$_SERVER["HTTP_USER_AGENT"]."\r\n";
$reqStr .=(($this->referer === "") ? "" : "Referer: ".$this->referer."\r\n");
$reqStr .=(($this->cookie != "") ? "Cookie: ".$this->cookie."\r\n" : "");
$reqStr .=(($this->method === "post") ? "Content-Length: ".strlen($this->postData)."\r\n" : "");
$reqStr .="Connection: Close\r\n\r\n";
$reqStr .=($this->method === "post" && !isset($this->postData)) ? $this->postData."\r\n\r\n" : "";
return $reqStr;
}
/// gzip解压缩
public function gzipDecode ($data) {
$flags = ord(substr($data, 3, 1));
$headerlen = 10;
$extralen = 0;
$filenamelen = 0;
if ($flags & 4) {
$extralen = unpack('v' ,substr($data, 10, 2));
$extralen = $extralen[1];
$headerlen += 2 + $extralen;
}
if ($flags & 8) // Filename
$headerlen = strpos($data, chr(0), $headerlen) + 1;
if ($flags & 16) // Comment
$headerlen = strpos($data, chr(0), $headerlen) + 1;
if ($flags & 2) // CRC at end of file
$headerlen += 2;
$unpacked = @gzinflate(substr($data, $headerlen));
if ($unpacked === FALSE)
$unpacked = $data;
return $unpacked;
}
/// chunked解码
public function chunkedDecode($data)
{
$pos = 0;
$temp = '';
while($pos < strlen($data))
{
$len = strpos($data, "/r/n", $pos) - $pos;
$str = substr($data, $pos, $len);
$pos += $len + 2;
$arr = explode(';', $str, 2);
$len = hexdec($arr[0]);
$temp .= substr($data, $pos, $len);
$pos += $len + 2;
}
return $temp;
}
/// 开始连接目标主机发送请求
public function action()
{
$RESULT = array();
/// 连接目标主机
$sock = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeOut);
if(!$sock)
{
/// 连接失败
$RESULT["error"] = $errstr;
}
else
{
$header = $content = "";
/// 设置阻塞模式
stream_set_blocking($sock, $this->blocked);
/// 设置超时
stream_set_timeout($sock, $this->timeOut);
/// 发送请求
fwrite($sock, $this->makeRequestStr());
/// 获取连接状态
$status = stream_get_meta_data($sock);
/// 判断是否超时
if(!$status["timed_out"])
{
/// 循环读取HTTP头部
while (!feof($sock))
{
$header .= $h = fgets($sock);
if($h && ($h == "\r\n" || $h == "\n")) break;
}
/// 解析头部
$RESULT = $this->parse_HTTP_Headers($header);
/// 循环读取正文
while(!feof($sock))
{
$data = fread($sock, $this->cacheSize);
$content .= $data;
}
/// 整合返回结果
if(array_key_exists("Content-Encoding", $RESULT))
{
/// gzip解压缩
if(strpos($RESULT["Content-Encoding"], "gzip") > -1)
{
$RESULT["Document_Body"] = $this->gzipDecode($content);
}
/// chunked解码
if(strpos($RESULT["Content-Encoding"], "chunked") > -1)
{
$RESULT["Document_Body"] = $this->chunkedDecode($content);
}
}
else
{
/// 未进行任何压缩编码直接返回结果
$RESULT["Document_Body"] = $content;
}
$RESULT["error"] = "";
}
else
{
/// 发送数据超时
$RESULT["error"] = "目标主机发送数据超时!";
}
}
/// 关闭连接
fclose($sock);
$sock = null;
/// 返回结果
return $RESULT;
}
}
?>