HTTP请求类 - HttpClient.class.php

本文介绍了一个名为HttpClient的PHP类,通过socket实现GET、POST和HEAD请求,详细解析HTTP请求与响应信息,包括如何使用get_headers()函数替代浏览器进行请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HTTPClient

写一个Http类,能更好的了解HTTP

在这里用 socket 模拟 get, post 请求,并得到结果,其中也加了 head 请求,用 php 自带的函数 get_headers()得到结果,代替了浏览器的请求工作。

1. HTTP请求与响应信息

  1.1 请求信息

请求行(Method URI HttpVersion)
请求头信息
空行
请求主体(主体可有可无)
  1.2 响应信息

响应行(HttpVersion StatusCode StatusDesc)
响应头信息
空行
请求主体(主体可有可无)

2. 用 Telnet 模拟请求
  这里在本机运行
  开始 -> 运行 -> cmd, 回车 -> telnet localhost 80, 回车 -> 按 Ctrl+], 再回车
  2.1 get 方式
    几乎所有的方式包含一个头信息
    Host: localhost(本机用localhost)

  2.2 post 方式
    可以照着完整的请求信息去灌水, 模拟登录...
    如果有表单内容要提交,需要包含
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 26(主体的长度)

  2.3 head 方式
    仅获取服务器响应信息


3. 用 php + socket 方式模拟请求
  直接贴代码,代码中有注释,实现 Telnet 中的请求 
  HttpClient.class.php code list

<?php
/**
 * http请求类(php + socket)
 * @todo 这里还有很多未完善的地方,仅有简单的get post head请求
 * @author chuangrain@gmail.com
 * @version 1.0.0
 */

class HttpClient {

    const CRLF = "\r\n";      //
    private $fh = null;       //socket handle
    private $errno = -1;      //socket open error no
    private $errstr = '';     //socket open error message
    private $timeout = 30;    //socket open timeout
    private $line = array();  //request line
    private $header = array();//request header
    private $body = array();  //request body
    private $url = array();   //request url
    private $response = '';   //response
    private $version = '1.1'; //http version
    
    public function __construct() {
        
    }
    
    /**
     * 发送HTTP get请求
     * @access public
     * @param string $url 请求的url
     */
    public function get($url = '') {
        $this->setUrl($url);
        $this->setLine();
        $this->setHeader();
        $this->request();
        return $this->response;
    }
    
    /**
     * 发送HTTP post请求
     * @access public
     */
    public function post() {
        $this->setLine('POST');
        $this->request();
        return $this->response;
    }
    
    /**
     * HTTP -> HEAD 方法,取得服务器响应一个 HTTP 请求所发送的所有标头
     * @access public
     * @param string $url 请求的url
     * @param int $fmt 数据返回形式,关联数组与普通数组
     * @return array 返回响应头信息
     */
    public function head($url = '', $fmt = 0) {
        $headers = null;
        if (is_string($url)) {
            $headers = get_headers($url, $fmt);
        }
        return $headers;
    }
    
    /**
     * 设置要请求的 url
     * @todo 这里未做url验证
     * @access public
     * @param string $url request url
     * @return bool
     */
    public function setUrl($url = '') {
        if (is_string($url)) {
            $this->url = parse_url($url);
            if (!isset($this->url['port'])) {//设置端口
                $this->url['port'] = 80;
            }
        } else {
            return false;
        }
    }
    
    /**
     * 设置HTTP协议的版本
     * @access public
     * @param string $version HTTP版本,default value = 1.1
     * @return bool 如果不在范围内返回false
     */
    public function setVersion($version = "1.1") {
        if ($version == '1.1' || $version == '1.0' || $version == '0.9') {
            $this->version = $version;
        } else {
            return false;
        }
    }
    
    /**
     * 设置HTTP请求行
     * @access public
     * @param string $method 请求方式 default value = GET
     */
    private function setLine($method = "GET") {
        //请求空:Method URI HttpVersion
        if (isset($this->url['query'])) {
            $this->line[0] = $method . " " . $this->url['path'] . "?" . $this->url['query'] . " HTTP/" . $this->version;
        } else {
            $this->line[0] = $method . " " . $this->url['path'] . " HTTP/" . $this->version;
        }
    }
    
    /**
     * 设置HTTP请求头信息
     * @access public
     * @param array $header 请求头信息
     */
    public function setHeader($header = null) {
        $this->header[0] = "Host: " . $this->url['host'];
        if (is_array($header)) {
            foreach($header as $k => $v) {
                $this->setHeaderKeyValue($k, $v);
            }
        }
    }
    
    /**
     * HTTP请求主体
     * @access public
     * @param array $body 请求主体
     */
    public function setBody($body = null) {
        if (is_array($body)) {
            foreach ($body as $k => $v) {
                $this->setBodyKeyValue($k, $v);
            }
        }
    }
    
    /**
     * 单条设置HTTP请求主体
     * @access public
     * @param string $key 请求主体的键
     * @param string $value 请求主体的值
     */
    public function setBodyKeyValue($key, $value) {
        if (is_string($key)) {
            $this->body[] = $key . "=" . $value;
        }
    }
    
    /**
     * 单条设置HTTP请求头信息
     * @access public
     * @param string $key 请求头信息的键
     * @param string $value 请求头信息的键
     */
    public function setHeaderKeyValue($key, $value) {
        if (is_string($key)) {
            $this->header[] = $key . ": " . $value;
        }
    }
    
    /**
     * socket连接host, 发送请求
     * @access private
     */
    private function request() {
        //构造http请求
        if (!empty($this->body)) {
            $bodyStr = implode("&", $this->body);
            $this->setHeaderKeyValue("Content-Length", strlen($bodyStr));
            $this->body[] = $bodyStr;
            $req = array_merge($this->line, $this->header, array(""), array($bodyStr), array(""));
        } else {
            $req = array_merge($this->line, $this->header, array(""), $this->body, array(""));
        }
        $req = implode(self::CRLF, $req);
        
        //socket连接host
        $this->fh = fsockopen($this->url['host'], $this->url['port'], $this->errno, $this->errstr, $this->timeout);
        
        if (!$this->fh) {
            echo "socket connect fail!";
            return false;
        }
        
        //写请求
        fwrite($this->fh, $req);
        
        //读响应
        while (!feof($this->fh)) {
            $this->response .= fread($this->fh, 1024);
        }
    }
    
    /**
     * 关闭socket连接
     * @access public
     */
    public function __destruct() {
        if ($this->fh) {
            fclose($this->fh);
        }
    }
    
}


$url = "http://localhost/xdebug/post_test.php";

/** get test **/
$http1 = new HttpClient();
var_dump($http1->get($url));

/** post test **/
$http2 = new HttpClient();
$header = array(
    "Content-Type" => "application/x-www-form-urlencoded"
);
$body = array(
    "username" => "1234",
    "submit" => "Login"
);
$http2->setUrl($url);
$http2->setHeader($header);
$http2->setBody($body);
var_dump($http2->post());

/** head test **/
$http3 = new HttpClient();
var_dump($http3->head($url, 1));
post_test.php code list
<?php

var_dump($_POST);

?>

<!DOCTYPE html>
<html>
    <head>
        <title>post request test</title>
    </head>
    <body>
        <form action="" method="post">
            <input type="text" name="username">
            <input type="submit" name="submit" value="Login">
        </form>
    </body>
</html>
运行结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值