Loading....

HEAD

  • 有一种精神,叫"公诚勤朴"

挣点外快

我的HTTP Client 模拟PHP Class
作者: wzhu 时间: 2009-06-22 17:35:18

最近因为要通过PHP调用REST接口,简单的写了一个模拟HTTPClient的PHP Class.相当于模拟浏览器操作.这是一个初始版本.等以后有时间了在完善下.如果有什么意见或者好的想法,欢迎指教.

<?php
/*
===========================================================    
    http.php    Zhu Weiwei
    Last    2009-08-20
    Copyright © 2006-2009
    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_charset      = 'UTF-8';
    private $m_accept       = '*/*';

    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_responseCookie = Array();
    private $m_responseBody = "";
    private $m_setbody      = false;

    private $m_maxLineLength= 1024;



    function __construct() {

    }

    function getResponseHead() {
        return $this->m_responseHead;
    }

    function getResponseBody() {
        return $this->m_responseBody;
    }

    function getResponseCookie() {
        return $this->m_responseCookie;
    }

    function getResponse() {
        return $this->m_response;
    }

    function getResponseStatus(){
        return $this->m_responseHead['Status'];
    }

    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 setHttpVersion($v){
        $v = strtoupper($v);
        switch($v){
        case "HTTP/1.0":
        case "HTTP/1.1":
            $this->m_httpVersion  = $v;
            break;
        }
    }

    function setMethod($m) {
        $m = strtoupper($m);
        switch($m){
        case 'OPTIONS':
        case 'HEAD':
        case 'GET':
        case 'POST':
        case 'PUT':       
        case 'DELETE':
        case 'TRACE':
        case 'CONNECT':
            $this->m_method=$m;
            break;   
        }
    }

    function setRequestBody($b) {
        $this->m_requestBody = $b;
        $this->m_setbody = true;
    }

    function setAccept($a) {
        $this->m_accept = $a;
    }

    function setEnctype($e) {
        $e = strtolower($e);
        switch($e){
        case "text/xml":
        case "application/xml":
        case "application/json":
        case "multipart/form-data":
        case "application/x-www-form-urlencoded":
        case "application/atom+xml":
            $this->m_enctype = $e;    
            break;
        }
    }
    
    function setReferer($r){
        $this->m_referer = $r;
    }

    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[] = urlencode($key)."=".urlencode($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= "$errstr ($errno)";                     break;
            }
            return false;
        }
    }

    function disconnect(){
        return(fclose($this->m_sock));
    }



    function parseHeadLine($line) {
        if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$line, $match)){
            $status = intval($match[1]);
            if($status < 100 or $status > 600){
                $status = 999;
            }
            $this->m_responseHead['Status'] = $status;
            if( $status >=400 ){
                $this->m_error = "An error occurred($status)!";
            }
        }
        else{
            if(preg_match('/^set-cookie:[\s]+([^=]+)=([^;]+)/i', $line,$match)){
                $this->m_responseCookie[$match[1]]=$match[2];
            }
            @list($key,$val) = explode(': ',$line,2);
            /* ?? Mult Set-Cookie ?? */
            $this->m_responseHead[$key] = $val;
        }
        @$this->m_responseHead['Content'] .= $line;
    }


    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->parseHeadLine($line);
            }


            /*
                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->CRLF.$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() {
        $body = $this->buildRequestBody();
        $head = $this->buildRequestHead();

        switch( $this->m_method ){
        #case "OPTIONS":
        #case "TRACE":
        #case "CONNECT":
        case "HEAD":
        case "GET":
        case "DELETE":
            $this->m_request = $head.$this->CRLF.$this->CRLF;
            break;

        case "PUT":
        case "POST":
            $this->m_request = $head.$this->CRLF.$this->CRLF.$body;
            break;
        }
        return $this->m_request;
    }

    function buildRequestURI() {
        if(!empty($this->m_query)){
            $this->m_uri .= '?'.$this->m_query;
        }
        if(!empty($this->m_fragment)){
            $this->m_uri .= '#'.$this->m_fragment;
        }           
    }

    function buildRequestHead() {
        #$this->buildRequestURI();
        $header = Array();
        switch( $this->m_method ){
        case "HEAD":
        case "GET":
        case "PUT":
        case "DELETE":
            $header[] ="$this->m_method $this->m_uri $this->m_httpVersion";
            break;
/*
        case "OPTIONS":
        case "TRACE":
        case "CONNECT":
*/
        case "PUT":
        case "POST":
            $header[] = "$this->m_method $this->m_uri $this->m_httpVersion";
            $header[] = "Content-Length: ".strlen($this->m_requestBody);  
            switch ($this->m_enctype) {
            case "application/x-www-form-urlencoded":
            case "application/xml":
            case "text/xml":
            case "application/json":
                $header[] ="Content-Type: $this->m_enctype";
                break;
            case "application/atom+xml":
                $header[] ="Content-Type: $this->m_enctype;type=entry";             
                break;
            case "multipart/form-data":
                $header[] ="Content-Type: multipart/form-data; boundary=$this->m_mimeBoundary";     
                break;
            default:
                $header[] ="Content-Type: ".$this->m_enctype;     
                break;
            }
            break;
        }

        if( intval($this->m_port) == 80 ){
            $header[] = "Host: $this->m_host";
        }else{
            $header[] = "Host: $this->m_host:$this->m_port";
        }

        $header[] = "Accept-Language: en";
        $header[] = "Accept-Charset: utf-8";
        
        if(!empty($this->m_accept)){
            $header[] = "Accept: $this->m_accept";
        }

        $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";
        
        if($this->m_httpVersion == 'HTTP/1.1'){
            $header[] = "Connection: Keep-Alive";
            $header[] = "Keep-Alive: 300";
        }else{
            $header[] = "Connection: Close";
        }

        if( !empty($this->m_referer) ){    
            $header[] = "Referer: $this->m_referer";
        }

        if(count($this->m_arrCookie) > 0){    
            $header[] = "Cookie: ".join("; ",$this->m_arrCookie);
        }                

        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() {
        if($this->m_setbody){
            return $this->m_requestBody;
        }

        $body = Array();
        switch( $this->m_method ){
        case "PUT":
        case "POST":
            switch ($this->m_enctype) {
            case "application/json":
                $this->m_requestBody = json_encode($this->m_arrParam);
                break;

            case "application/x-www-form-urlencoded":
                foreach( $this->m_arrParam as $key=>$val) {
                    $body[] = urlencode($key)."=".urlencode($val);
                }
                $this->m_requestBody = join("&",$body);
                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;
            }
            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->setEnctype("multipart/form-data");
$oHTTP->addParameter("param","value");
$oHTTP->addFile("filedata","/tmp/tmpFile");
if( !$oHTTP->sendRequest() ){
    print($oHTTP->getError());
    exit();
}
$request  = $oHTTP->getRequest();
$response = $oHTTP->getResponse();
print($response);

 

相关评论
发表评论
姓名:
图码: