同福

做个web框架(21)——HTTP客户端对象TFHttpClient的实现【20201230】

介绍

介绍

福哥今天带着大家给TFPHP框架添加一个非常重要的功能模块——TFHttpClient。在很多情况下,我们的控制器需要通过远程的方式调用接口上的数据或者功能,因为这些接口可能属于其他系统或者其他服务,从本地无法直接访问。

这种通过远程方式访问接口就需要借助可以模拟浏览器进行网站访问工具对象来完成,因为网站或者平台是遵循HTTP协议的,所以只要是符合HTTP协议的客户端工具都可以实现这个功能。

在PHP语言里面有个curl扩展,它实现了几乎所有HTTP协议支持的全部功能,我们通过调用这个curl扩展就可以实现通过PHP程序模拟浏览器访问远程接口的功能了。

TFHttpClient

TFHP\Socket\TFHttpClient

public static function create(TFPHP $a):TFHttpClient{
    $b=new TFHttpClient($a);
    return $b;
}
public function get():TFHttpClientHeader{
    $a=new TFHttpClientHeader($this->a,$b);
    $a->setMethod("get");
    return $a;
}
public function post():TFHttpClientBody{
    $a=new TFHttpClientBody($this->a,$b);
    $a->setMethod("post");
    return $a;
}
public function delete():TFHttpClientHeader{
    $a=new TFHttpClientHeader($this->a,$b);
    $a->setMethod("delete");
    return $a;
}
public function put():TFHttpClientBody{
    $a=new TFHttpClientBody($this->a,$b);
    $a->setMethod("put");
    return $a;
}
public function head():TFHttpClientHeader{
    $a=new TFHttpClientHeader($this->a,$b);
    $a->setMethod("head");
    return $a;
}

TFHttpClientRequest

TFHP\Socket\HttpClient\TFHttpClientRequest

protected function setUri(string $a){
    $this->d=$a;
}
protected function setHeaders(array $a){
    $this->e=$a;
}
protected function setCookies(array $a){
    $this->f=$a;
}
protected function setBody(array $a){
    $this->g=$a;
}
public function setMethod(string $a){
    $this->c=strtolower($a);
}
public function retrieve():TFHttpClientResponse{
    $a=new TFHttpClientResponse($this->a,$this->b,$b,array($this->c,$this->d,$this->e,$this->f,$this->g,$this->h));
    return $a;
}

TFHttpClientHeader

TFHP\Socket\HttpClient\TFHttpClientHeader

public function uri(string $a):TFHttpClientHeader{
    $this->setUri($a);
    return $this;
}
public function headers(array $a):TFHttpClientHeader{
    $this->setHeaders($a);
    return $this;
}
public function cookies(array $a):TFHttpClientHeader{
    $this->setCookies($a);
    return $this;
}

TFHttpClientBody

TFHP\Socket\HttpClient\TFHttpClientBody

public function uri(string $a):TFHttpClientBody{
    $this->setUri($a);
    return $this;
}
public function headers(array $a):TFHttpClientBody{
    $this->setHeaders($a);
    return $this;
}
public function cookies(array $a):TFHttpClientBody{
    $this->setCookies($a);
    return $this;
}
public function body(array $a):TFHttpClientBody{
    $this->setBody($a);
    return $this;
}

TFHttpClientResponse

TFHP\Socket\HttpClient\TFHttpClientResponse

private function a(?array $a):string{
    $b="";
    if(is_array($a)){
        foreach($a as  $c=>$d){
            $b.=";".$c."=".urlencode($d);
        }
        if($b!=""){
            $b=substr($b,1);
        }
    }
    return $b;
}
private function b(?array $a):string{
    $b="";
    if(is_array($a)){
        foreach($a as  $c=>$d){
            $b.="&".$c."=".urlencode($d);
        }
        if($b!=""){
            $b=substr($b,1);
        }
    }
    return $b;
}
private function c(?array $a,string $b,string $c):array{
    if(is_array($a)){
        foreach($a as  $d=>$e){
            $a[strtoupper($d)]=$e;
            unset($a[$d]);
        }
    }
    if(!isset($a['EXPECT'])){
        $a['EXPECT']="";
    }
    if(!isset($a['HOST'])){
        $a['HOST']=$b;
    }
    if(isset($a['CONTENT-TYPE'])){
        $a['CONTENT-LENGTH']=0;
        if(strpos($a['CONTENT-TYPE'],"application/json")==0){
            $a['X-HTTP-METHOD-OVERRIDE']=$c;
        }
    }
    return $a;
}
private function d(?array $a):array{
    $b=array();
    if(is_array($a)){
        foreach($a as  $c=>$d){
            $e=preg_replace_callback("/[a-zA-Z0-9]+/",function ($a){
                $b=strtolower($a[0]);
                if($b=="http"){
                    return"HTTP";
                }
                return strtoupper($b[0]).substr($b,1);
            }
            ,$b);
            $c[]=$d.": ".$e;
        }
    }
    return $c;
}
private function e(){
    $a=curl_init();
    $b=$this->d[1];
    $c=parse_url($b);
    $d=$c['host'];
    curl_setopt($a,CURLOPT_URL,$b);
    curl_setopt($a,CURLOPT_FOLLOWLOCATION,1);
    curl_setopt($a,CURLOPT_MAXREDIRS,10);
    curl_setopt($a,CURLOPT_RETURNTRANSFER,1);
    $e=$this->d[0];
    curl_setopt($a,CURLOPT_CUSTOMREQUEST,$e);
    $f=$this->d[2];
    $f=$this->c($f,$d,$e);
    $g="";
    if(strpos($f['CONTENT-TYPE'],"application/json")==0){
        $g=json_encode($this->d[4]);
    }
    else if(strpos($f['CONTENT-TYPE'],"application/x-form-urlencoded")==0){
        $g=$this->b($this->d[4]);
    }
    else if($f['CONTENT-TYPE']!=""){
        $g=$this->d[5];
    }
    if($g!=""){
        $f['CONTENT-LENGTH']=strlen($g);
        curl_setopt($a,CURLOPT_POSTFIELDS,$g);
    }
    $h=$this->d($f);
    curl_setopt($a,CURLINFO_HEADER_OUT,1);
    curl_setopt($a,CURLOPT_HEADER,1);
    curl_setopt($a,CURLOPT_HTTPHEADER,$h);
    $i=$this->d[3];
    $j=$this->a($i);
    if($j!=""){
        curl_setopt($a,CURLOPT_COOKIE,$j);
    }
    $k=curl_exec($a);
    $l=curl_getinfo($a,CURLINFO_HEADER_OUT);
    $m="";
    $n=strpos($k,"\r\n\r\n");
    if($n!==false){
        $m=substr($k,0,$n+4);
        $k=substr($k,$n+4);
    }
    $o=curl_error($a);
    curl_close($a);
    $this->e=$k;
    $this->f=$o;
    var_dump($k);
    var_dump($l);
    var_dump($m);
    var_dump($o);
}
public function getResponse():?string{
    return $this->e;
}
public function getResponseJson():array{
    return array();
}
public function getLastError():?string{
    return $this->f;
}

讲解

TFHttpClient

create

这个是一个静态方法,用来创建一个TFHttpClient对象的实例

get

通过get方法启动一个实现模拟GET请求的实例

post

通过post方法启动一个实现模拟POST请求的实例

put

通过put方法启动一个实现模拟PUT请求的实例,通常情况下RESTFul规范下会有这种方式

delete

通过delete方法启动一个实现模拟PUT请求的实例,通常情况下RESTFul规范下会有这种方式

head

通过head方法启动一个实现模拟PUT请求的实例

TFHttpClientRequest

setUri

设置请求的URI地址,可以包含QUERY_STRING部分

setHeaders

设置请求的HTTP头信息,必须数组格式

setCookies

设置请求的COOKIE信息,必须数组格式

setBody

设置请求的数据,只有POST或者PUT方式才有这个功能

setMethod

一般情况下不需要自己调用

retrieve

根据请求参数提交一个HTTP的访问请求,并获取远程服务器执行结果


TFHttpClientHeader

uri

调用父类setUri

headers

调用父类setHeaders

cookies

调用父类setCookies

TFHttpClientBody

uri

调用父类setUri

headers

调用父类setHeaders

cookies

调用父类setCookies

body

调用父类setBody

TFHttpClientResponse

a

组织COOKIE参数

b

组织请求数据

c

组织请求头信息

d

创建完整的HTTP请求头

e

请求服务器资源,获取服务器响应数据

getResponse

获取服务器响应数据

getResponseJson

尝试以JSON格式解析服务器响应数据

getLastError

获取最后一次请求的错误信息

使用

模拟GET请求

c4a71440d1054b21.jpg

模拟POST请求

36f72d9d5c7535e9.jpg

总结

福哥今天带着童鞋们给TFPHP框架添加了TFHttpClient模块,有了这个HTTP客户端工具对象我们就可以在程序里面模拟浏览器访问远程服务器的页面或者接口了。

在大型的网站平台里,功能调用都是采用的这种远程接口调用的方式实现了,这种方式有一种专用的称呼叫做——RPC(Remote Process Call),使用RPC替代传统的包引用的方式在不同模块之间进行功能的调用可以大大的降低程序代码由于业务逻辑过度复杂而导致的异常情况的发生。

好了,福哥今后会不断地给我们的TFPHP框架添砖加瓦,让她越来越完美!