最近因为要通过PHP调用REST接口,简单的写了一个模拟HTTPClient的PHP Class.相当于模拟浏览器操作.这是一个初始版本.等以后有时间了在完善下.如果有什么意见或者好的想法,欢迎指教.
<?php
/*
===========================================================
HTTP.php Zhu Weiwei
Copyright © 2006-2008
http://www.cncmm.com China. All Rights Reserved.
===========================================================
*/
class HTTP{
private $m_httpVersion = "HTTP/1.0";
private $m_method = "GET";
private $m_enctype = "application/x-www-form-urlencoded";
private $m_scheme = "http";
private $m_host = "127.0.0.1";
private $m_port = 80;
private $m_path = "/";
private $m_query = "";
private $m_fragment = "";
private $m_user = "";
private $m_pass = "";
private $m_uri = "/";
private $m_referer = "";
private $m_mimeBoundary = "";
private $m_sockTimeout = 10;
private $m_readTimeout = 10;
private $m_timeout = false;
private $m_sock = "";
private $m_error = "";
private $CRLF = "\r\n";
private $m_arrParam = Array();
private $m_arrFile = Array();
private $m_arrCookie = Array();
private $m_request = "";
private $m_requestHead = "";
private $m_requestBody = "";
private $m_response = "";
private $m_responseHead = Array();
private $m_responseBody = "";
private $m_maxLineLength= 1024;
function __construct() {
}
function getResponseHead() {
return $this->m_responseHead;
}
function getResponseBody() {
return $this->m_responseBody;
}
function getResponse() {
return $this->m_response;
}
function getRequestHead() {
return $this->m_requestHead;
}
function getRequestBody() {
return $this->m_requestBody;
}
function getRequest() {
return $this->m_request;
}
function getError() {
return $this->m_error;
}
function setMethod($m) {
$this->m_method = (strtoupper($m=='POST'))?('POST'):('GET');
}
function setEnctype($e) {
$this->m_enctype = (strtolower($e)=='application/x-www-form-urlencoded')?
('application/x-www-form-urlencoded'):('multipart/form-data');
}
function setURL($url) {
$rs = parse_url($url);
$this->m_scheme = empty($rs['scheme']) ?('http') :($rs['scheme']);
$this->m_host = empty($rs['host']) ?('localhost'):($rs['host']);
$this->m_port = empty($rs['port']) ?('80') :($rs['port']);
$this->m_user = empty($rs['user']) ?('') :($rs['user']);
$this->m_pass = empty($rs['pass']) ?('') :($rs['pass']);
$this->m_path = empty($rs['path']) ?('/') :($rs['path']);
$this->m_query = empty($rs['query']) ?('') :($rs['query']);
$this->m_fragment = empty($rs['fragment'])?('') :($rs['fragment']);
$this->m_uri = $this->m_path;
if(!empty($this->m_query)){
$this->m_uri .= '?'.$this->m_query;
}
if(!empty($this->m_fragment)){
$this->m_uri .= '#'.$this->m_fragment;
}
}
function addParameter($key,$val) {
if(!empty($key)){
$this->m_arrParam[$key] = $val;
}
}
function addFile($key,$file) {
if(!empty($key) && file_exists($file)){
$this->m_arrFile[$key] = $file;
}
}
function addCookie($key,$val) {
if(!empty($key)){
$this->m_arrCookie[$key] = $val;
}
}
function connect() {
$this->m_sock = fsockopen($this->m_host,
$this->m_port,
$errno,
$errstr,
$this->m_sockTimeout);
if($this->m_sock){
return true;
}else{
switch($errno){
case -3: $this->m_error="socket creation failed (-3)"; break;
case -4: $this->m_error="dns lookup failure (-4)"; break;
case -5: $this->m_error="connection refused or timed out (-5)"; break;
default: $this->m_error="connection failed (".$errno.")"; break;
}
return false;
}
}
function disconnect(){
return(fclose($this->m_sock));
}
function sendRequest() {
if($this->connect()){
$this->buildRequest();
socket_set_timeout($this->m_sock, $this->m_readTimeout);
fwrite($this->m_sock, $this->m_request, strlen($this->m_request));
/*
Get And Parse HTTP Header
*/
while( !feof($this->m_sock) )
{
if( $this->m_readTimeout > 0 && $this->checkResponseTimeOut() ){
return false;
}
$line = fgets($this->m_sock, $this->m_maxLineLength);
if($line == $this->CRLF )
break;
$this->m_responseHead['Content'] .= $line;
if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$line, $status)){
$this->m_responseHead['Status'] = $status[1];
}else{
list($key,$val) = explode(': ',$line,2);
$this->m_responseHead[$key] = $val;
}
}
/*
Get HTTP Body
*/
while(!feof($this->m_sock) ) {
if( $this->m_readTimeout > 0 && $this->checkResponseTimeOut() ){
return false;
}
$this->m_responseBody .= fgets($this->m_sock, $this->m_maxLineLength);
}
$this->m_response = $this->m_responseHead['Content'].$this->m_responseBody;
$this->disconnect();
return true;
}else{
return false;
}
}
function checkResponseTimeOut()
{
if ($this->m_readTimeout > 0) {
$fp_status = socket_get_status($this->m_sock);
if ($fp_status["timed_out"]) {
$this->m_error="read response timeout!";
return true;
}
}
return false;
}
function buildRequest() {
switch( $this->m_method ){
case "POST":
$body = $this->buildRequestBody();
$head = $this->buildRequestHead();
$this->m_request = $head.$this->CRLF.$this->CRLF.$body;
break;
case "GET":
$head = $this->buildRequestHead();
$this->m_request = $head.$this->CRLF.$this->CRLF;
break;
}
return $this->m_request;
}
function buildRequestHead() {
$header = Array();
switch( $this->m_method ){
case "POST":
$header[] ="POST $this->m_uri $this->m_httpVersion";
$header[] = "Content-Length: ".strlen($this->m_requestBody);
switch ($this->m_enctype) {
case "application/x-www-form-urlencoded":
$header[] ="Content-Type: application/x-www-form-urlencoded";
//$header[] ="Content-Type: application/xml; charset=UTF-8";
break;
case "multipart/form-data":
$header[] ="Content-Type: multipart/form-data; boundary=$this->m_mimeBoundary";
break;
}
break;
case "GET":
$header[] ="GET $this->m_uri $this->m_httpVersion";
break;
}
$header[] = "Cache-Control: no-cache";
$header[] = "Pragma: no-cache";
$header[] = "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.11) Gecko/2009060215 Firefox/3.0.11";
$header[] = "Accept: */*";
#$header[] = "Accept-Language: zh-cn";
#$header[] = "Accept-Encoding: gzip,deflate";
#$header[] = "Accept-Charset: utf-8";
$header[] = "Connection: Keep-Alive";
$header[] = "Keep-Alive: 300";
//$header[] = "Connection: Close";
//$header[] = "Referer: $this->m_referer";
//$header[] = "Cookie: ".join(';',$this->m_arrCookie);
if( intval($this->m_port) == 80 ){
$header[] = "Host: $this->m_host";
}else{
$header[] = "Host: $this->m_host:$this->m_port";
}
if(!empty($this->m_user) || !empty($this->m_pass)){
$header[] = "Authorization: Basic ".base64_encode($this->m_user.":".$this->m_pass);
}
$this->m_requestHead = join($this->CRLF, $header);
return $this->m_requestHead;
}
function buildRequestBody() {
$body = Array();
switch ($this->m_enctype) {
case "application/x-www-form-urlencoded":
foreach( $this->m_arrParam as $key=>$val) {
$body[] = urlencode($key)."=".urlencode($val);
}
$this->m_requestBody = join("&",$body);
//$this->m_requestBody = json_encode($this->m_arrParam); //For Rest
break;
case "multipart/form-data":
$this->m_mimeBoundary = '<'.base64_encode(uniqid(microtime(),true)).'=>';
foreach( $this->m_arrParam as $key=>$val) {
$body[] = "--".$this->m_mimeBoundary;
$body[] = "Content-Disposition: form-data; name=\"$key\"".$this->CRLF;
$body[] = $val;
}
foreach( $this->m_arrFile as $key=>$filename) {
$body[] = "--".$this->m_mimeBoundary;
$body[] = "Content-Disposition: form-data; name=\"$key\"; filename=\"$filename\"";
$body[] = "Content-Type: application/octet-stream";
$body[] = "Content-Transfer-Encoding: Binary".$this->CRLF;
$body[] = file_get_contents($filename);
}
$body[] = "--".$this->m_mimeBoundary."--".$this->CRLF;
$this->m_requestBody = join($this->CRLF,$body);
break;
}
return $this->m_requestBody;
}
};
example.php
<?php
require_once("http.php");
$oHTTP = new HTTP();
$oHTTP->setURL("http://www.cncmm.com/");
$oHTTP->setMethod("POST");
$oHTTP->addParameter("param","value");
$oHTTP->addFile("filedata","/tmp/tmpFile");
if( !$oHTTP->sendRequest() ){
print($oHTTP->getError());
exit();
}
$request = $oHTTP->getRequest();
$response = $oHTTP->getResponse();
print($response);