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
PHP

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?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);
}
}