You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
information-system/application/third_party/flight/libraries/API/class/MyHttp.class.php

281 lines
6.2 KiB
PHTML

<?php
/* PHP SDK
* @version 2.0.0
* @author magicsky0@163.com
* @copyright © 2014, Ctrip Corporation. All rights reserved.
*/
class MyHttp
{
public $url;
public $method;
public $timeout = 15;
public $type;
public $responed;
private $_host;
private $_uri;
private $_port = 80;
private $_header = array();
private $_body = '';
/**
* @param stirng $url
* @param stirng $method get|post
* @param stirng $type smart|curl|socket|fscoket
* @param int $timeout
*/
public function __construct( $url, $type='smart', $method='post', $timeout=15)
{
$this->url = $url;
$this->method = 'POST'; // strtoupper($method) TODO:暂时只支持POST
$this->type = strtolower($type);
$this->timeout = $timeout;
$this->parse_url();
}
private function parse_url()
{
preg_match("/^http\:\/\/([^\:\/]+?)(\:(\d+))?\/(.+?)$/is", $this->url, $match);
$this->_host = $match[1];
$this->_uri = '/'.$match[4];
$this->_port = !empty($match[2])?intval($match[3]):80;
}
public function set_header($request, $options = array() )
{
$header['Accept'] = '*/*';
$header['Accept-Language'] = 'zh-cn';
$header['Accept-Encoding'] = '';
$header['Transfer-Encoding'] = '';
if( extension_loaded('zlib') && function_exists('gzdecode') )
{
$header['Accept-Encoding'] = 'gzip,deflate'; // open api服务器默认为此设置
//$header['Transfer-Encoding'] = 'chunked'; // gzip后Content-Length长度不确定
}
$header['User-Agent'] = 'HttpRequest Class 1.1';
$header['Host'] = $this->_host;
$header['Connection'] = 'close';
$header['Content-Length'] = strlen($request);
$header['Content-Type'] = 'text/xml;charset=utf-8';
// 允许覆盖上面的默认配置项
if( !empty($options) )
{
$header = array_merge( $header, $options );
}
$this->_header = $header;
}
public function send($request)
{
debugger($request,'Request Entity');
$this->set_header($request);
switch ($this->type)
{
case 'stream' : $this->stream($request); break;
case 'curl' : $this->curl($request); break;
case 'socket' : $this->socket($request); break;
case 'fsocket' : $this->fsocket($request); break;
default : $this->smart($request);
}
debugger($this->responed,'Responed Entity');
return $this->responed;
}
private function encode_respond( $buffer )
{
debugger($buffer,'Buffer Entity');
$header = $body = '';
$p = strpos( $buffer, "\r\n\r\n" );
// 去除头部信息
if( $p > 0 )
{
$header = substr( $buffer, 0, $p );
if( $p+4 < strlen($buffer) )
{
$body = substr( $buffer, $p+4 );
}
}
// 如果header为续传标记则继续去除头部信息
if( $header = 'HTTP/1.1 100 Continue' )
{
$p = strpos( $body, "\r\n\r\n" );
if( $p > 0 )
{
$header = substr( $body, 0, $p );
if( $p+4 < strlen($body) )
{
$body = substr( $body, $p+4 );
}
}
}
/*
$body_without_header = '';
$p2 = strpos( $buffer, "<?xml" ); // 第一次出现XML标记的位置
if( $p2 > 1 )
{
if( $p2-1 < strlen($buffer) )
{
$body_without_header = substr( $buffer,$p2-1 );
}
}
*/
try
{
if( $this->_header['Accept-Encoding'] == 'gzip,deflate' )
{
$body = @gzdecode($body);
if( !$body )
{
trigger_error('返回体解析错误',E_USER_WARNING);
}
}
if( $this->_header['Transfer-Encoding'] == 'chunked' )
{
$body = @http_chunked_decode($body);
}
}
catch( Exception $e )
{
trigger_error($e);
}
return $body;
}
// 智能选择通信模式
private function smart($request)
{
if ( function_exists('curl_init') )
{
$this->curl($request);
return TRUE;
}
if ( function_exists('fsockopen') )
{
$this->fsocket($request);
return TRUE;
}
if ( function_exists('stream_context_create') )
{
$this->stream($request);
return TRUE;
}
trigger_error('您的系统环境不支持远程调用!',E_USER_ERROR);
}
private function stream($request)
{
$header = '';
foreach($this->_header as $keys => $value)
{
$header .= "$keys: $value\r\n";
}
$opts = array(
'http' => array(
'method' => $this->method,
'header' => $header,
'content' => $request
)
);
$context = stream_context_create($opts);
$fp = fopen($this->url, 'r', FALSE, $context);
$buffer = stream_get_contents($fp);
fclose($fp);
$this->responed = $buffer;
}
private function curl($request)
{
foreach($this->_header as $keys => $value)
{
$header[] = "$keys:$value";
}
$body = $request;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->url);
curl_setopt($ch, CURLOPT_PORT, $this->_port);
curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
curl_setopt($ch, CURLOPT_HEADER, TRUE); // 启用时会将头文件的信息作为数据流输出
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); // 在启用时返回原生的Raw输出
$buffer = curl_exec($ch);
curl_close($ch);
$this->responed = $this->encode_respond($buffer);
}
private function socket($request)
{
$body = "$this->method $this->_uri HTTP/1.1\r\n";
foreach($this->_header as $keys => $value)
{
$body .= "$keys: $value\r\n";
}
$body .= "\r\n".$request;
$fp = socket_create(AF_INET,SOCK_STREAM,0);
socket_connect($fp, $this->_host, $this->_port); // openapi.ctrip.com
socket_write($fp,$body);
$timestart = time();
$buffer = $tmp = '';
do{
$buffer .= $tmp;
$tmp = socket_read($fp,4096);
}
while( $tmp && (time()-$timestart) <= $this->timeout );
socket_close($fp);
$this->responed = $this->encode_respond($buffer);
}
private function fsocket($request)
{
$body = "$this->method $this->_uri HTTP/1.1\r\n";
foreach($this->_header as $keys => $value)
{
$body .= "$keys: $value\r\n";
}
$body .= "\r\n".$request;
$fp = fsockopen($this->_host, $this->_port, $errno, $errstr, $this->timeout);
fputs($fp, $body);
$timestart = time();
$buffer = '';
while( !feof($fp) && (time()-$timestart) <= $this->timeout )
{
$buffer .= fgets($fp,4096);
}
fclose($fp);
$this->responed = $this->encode_respond($buffer);
}
}