首页 > PHP > 不使用curl的CURLOPT_COOKIE实现带cookie请求

不使用curl的CURLOPT_COOKIE实现带cookie请求

我们知道php的curl扩展可以使用curl_setopt($DATA_POST, CURLOPT_COOKIEJAR, 'cookie.txt');将http响应结果的头部中的Set-Cookie:存入到cookie.txt文件中;而且使用curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');可以将cookie.txt文件中的cookie附加到http请求的头部。

然而当我们没有安装curl扩展的时候需要手动实现cookie的保存与读取。下面使用file_get_contents来实现cookie的保存与读取。

<?php
/** 
 * 发送http请求
 * @param $url 请求地址
 * @param $postFields HTTP方法为POST时的请求参数
 * @param $http_headers HTTP请求头部设置
 * @return string HTTP请求相应结果
 */
function request_url($url, $postFields = null, $http_headers = array())
{
    $crlf = "\r\n";
    $timeout = 10;
    if(!empty($postFields))
    {
        $http_headers['Content-type'] = 'application/x-www-form-urlencoded';
        $context = array(
            'http'=>array(
                'method' => 'POST', 
                'timeout' => $timeout,
                'content' => http_build_query($postFields),                                 //get提交的时候不能指定content,否则报错
            ),
        );
    }else{
        $context = array(
            'http'=>array(
                'method' => 'GET', 
                'timeout' => $timeout,
                'content' => '',
            ),
        );
    }
    
    // 请求之前附加cookie到request header
    if(!isset($http_headers['Cookie']))
    {
        $http_headers['Cookie'] =  COOKIE::toString();
    }
    $header = array();
    foreach($http_headers as $k => $v)
    {
        $header[] = "$k: $v";
    }
    $context['http']['header'] = implode($crlf, $header);
    $result = @file_get_contents($url, false, stream_context_create($context));
    // 使用file_get_contents获取的头部信息会被存入到$http_response_header变量中
    foreach($http_response_header as $line)
    {
        // 如果reponse header中含有Set-Cookie的指令
        if(strpos($line, 'Set-Cookie:') !== false)
        {
            $pos = strpos($line, ';');
            $expire = substr($line, $pos);
            $start = strlen('Set-Cookie:');
            $line = trim(substr($line, $start, $pos-$start));
            $kv = explode('=', $line);
            $exp = explode('=', $expire);
            // 获取cookie过期时间并判断cookie是否过期, 如果后端设置立刻过期将会执行删除cookie方法
            if(isset($exp[1]) && time() - strtotime($exp[1]) >= 0)
            {
                COOKIE::set($kv[0], urldecode($kv[1]));
            }else{
                // 将cookie保存到文件, 如果不考虑cookie即将过期的问题将会永久保存到文件
                COOKIE::set($kv[0], urldecode($kv[1]));
            }
        }
    }
    return $result;
}
/*
 *使用文件记录cookie
*/
class COOKIE
{
    public static $path = 'cookie.txt';
    public static $sep = '; ';
    
    // 存cookie
    public static function set($key, $value)
    {
        if(is_null(self::get($key)))
        {
            file_put_contents(self::$path, $key.'='.rawurlencode($value).self::$sep, FILE_APPEND | LOCK_EX);
        }
    }
    
    // 取cookie
    public static function get($key)
    {
        if(file_exists(self::$path))
        {
            //将文件的内容读取到数组中
            $contents = file_get_contents(self::$path);
            $lines = explode(self::$sep, $contents);
            //遍历数组,进行匹配
            foreach($lines as $line)
            {
                // 查找相关cookie是否存在
                $kv = explode('=', $line);
                if($key == trim($kv[0]))
                {
                    return trim(rawurldecode($kv[1]));
                }
            }
        }
        return null;
    }
    
    // 删cookie
    public static function del($key)
    {
        if(is_null(self::get($key)))
        {
            return false;
        }else{
            $contents = file_get_contents(self::$path);
            $lines = explode(self::$sep, $contents);
            $flag = false;
            file_put_contents(self::$path, '');
            foreach($lines as $line)
            {
                if(empty($line))
                {
                    continue;
                }
                $kv = explode('=', $line);
                
                if($key != trim($kv[0]))
                {
                    file_put_contents(self::$path, $kv[0].'='.$kv[1].self::$sep, FILE_APPEND | LOCK_EX);
                }
            }
            return true;
        }
        
    }
    
    // 串化
    public static function toString()
    {
        if(file_exists(self::$path))
        {
            return rtrim(file_get_contents(self::$path), self::$sep);
        }else{
            return '';
        }
    }
}

使用request_url模拟http请求的头部的时候,需要手动传入第三个参数进行设置,虽然没有curl_setopt方便,但是同样可以达到设置http请求头部的效果。唯一的遗憾在于目前还没实现cookie的即将过期功能。之前有查过chrome浏览器的cookie保存方式为SQLite format,而IE浏览器的cookie保存方式则是txt文本,格式如下:

a
aaaa
127.0.0.1/
1536
2649695360
30491215
3434478224
30491131
*
b
bbbb
127.0.0.1/
1536
2649695360
30491215
3434508224
30491131
*

按道理来说实现起来并不难,可是使用curl扩展更方便,只需要传入2个参数即可实现cookie的自动管理。

这里的代码只是给出一个cookie的传输原理作为案例,实际工作中像snoopy这样的类库在http封装上更适合我们使用。

snoopy.class.php下载:Snoopy-2.0.0.tar.gz.zip


教程网址:http://blog.zhengshuiguang.com/php/curl-cookie.html

欢迎收藏∩_∩但请保留本文链接。

标签:cookie curl file_get_contents

相关文章

评论已关闭