php的fsockopen伪造请求头,获取相应数据

http请求包含三个部分,请求行(\r\n)请求头(\r\n\r\n)请求主体

http相应包含三部分,状态行(\r\n)响应头(\r\n\r\n)响应主体

起始行与header之间通过一个换行符分隔(\r\n),多个header字段之间也是通过换行符分隔(\r\n),报文首部与报文主体之间则通过一个一个空行分隔(\r\n\r\n),报文首部有纯文本格式的字符串组成,报文主体则可以包含多种格式数据。

HTTP 报文之 POST 报文

php的 fsockopen可以让我们自己构造请求header,获取响应header和响应主体数据 

/**
 * 使用fsockopen发送URL请求
 * @param $url
 * @param $method: GET、POST等
 * @param array $params
 * @param array $header
 * @param int $timeout
 * @return array|bool
 */
function sendHttpRequest($url, $method = 'GET', $params = [], $header = [], $timeout = 30)
{
    $urlInfo = parse_url($url);
 
    if (isset($urlInfo['scheme']) && strcasecmp($urlInfo['scheme'], 'https') === 0) //HTTPS
    {
        $prefix = 'ssl://';
        $port = 443;
    }else{  //HTTP
        $prefix = 'tcp://';
        $port = isset($urlInfo['port']) ? $urlInfo['port'] : 80;
    }
 
    $host = $urlInfo['host'];
    $path = isset($urlInfo['path']) ? $urlInfo['path'] : '/';
 
    if(!empty($params) && is_array($params))
    {
        $params = http_build_query($params);
    }
 
    $contentType = '';
    $contentLength = '';
    $requestBody = '';
    if($method === 'GET')
    {
        $params = $params ? '?' . $params : '';
        $path .= $params;
    }else{
        $requestBody = $params;
        $contentType = "Content-Type: application/x-www-form-urlencoded\r\n";
        $contentLength = "Content-Length: " . strlen($requestBody) . "\r\n";
    }
 
 
    $auth = '';
    if(!empty($urlInfo['user']))
    {
        $auth = 'Authorization: Basic ' . base64_encode($urlInfo['user'] . ':' . $urlInfo['pass']) . "\r\n";
    }
 
    if($header && is_array($header))
    {
        $tmpString = '';
        foreach ($header as $key => $value)
        {
            $tmpString .= $key . ': ' . $value . "\r\n";
        }
        $header = $tmpString;
    }else{
        $header = '';
    }
 
    $out = "$method $path HTTP/1.1\r\n";
    $out .= "Host: $host\r\n";
    $out .= $auth;
    $out .= $header;
    $out .= $contentType;
    $out .= $contentLength;
    $out .= "Connection: Close\r\n\r\n";
    $out .= $requestBody;//post发送数据前必须要有两个换行符\r\n
     
    //返回一个句柄$fp
    $fp = fsockopen($prefix . $host, $port, $errno, $errstr, $timeout);
    if(!$fp)
    {
        return false;
    }
     
    //向$fp写入请求报文
    if(!fwrite($fp, $out))
    {
        return false;
    }
 
    $response = '';
    
    //读取$fp就是读取响应数据
    while(!feof($fp))
    {
        $response .= fread($fp, 1024);
    }
 
    if(!$response)
    {
        return false;
    }
 
    fclose($fp);
 
    $separator = '/\r\n\r\n|\n\n|\r\r/';
 
    list($responseHeader, $responseBody) = preg_split($separator, $response, 2);
 
    $httpResponse = array(
        'header' => $responseHeader,
        'body' => $responseBody
    );
 
    return $httpResponse;
}

猜你喜欢

转载自blog.csdn.net/littlexiaoshuishui/article/details/106334527