不使用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
欢迎收藏∩_∩但请保留本文链接。
评论已关闭