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, " 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); } }