Web

Как получить куки из php curl в переменную

Какой-то разработчик из другой компании решил, что было бы здорово, если бы вместо использования soap или xml-rpc, или rest, или любого другого разумного протокола связи он просто встроил бы все свои ответы в виде cookies в заголовок.

Мне нужно извлечь эти куки в виде массива из ответа curl. Если мне придется потратить кучу времени на написание парсера для этого, я буду очень недоволен.

Кто-нибудь знает, как это можно просто сделать, желательно не записывая ничего в файл? Я буду очень благодарен, если кто-нибудь сможет мне в этом помочь.

 

Ответ 1

$ch = curl_init('http://www.google.com/');

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// получить заголовки с помощью этой строки

curl_setopt($ch, CURLOPT_HEADER, 1);

$result = curl_exec($ch);

// получить cookie

preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $result, $matches);

$cookies = array();

foreach($matches[1] as $item) {

    parse_str($item, $cookie);

    $cookies = array_merge($cookies, $cookie);

}

var_dump($cookies);

 

Ответ 2

Хотя этот вопрос довольно стандартный, и предыдущий ответ действителен, я нахожу его немного неудобным, потому что содержимое HTTP-ответа (HTML, XML, JSON, двоичный или любой другой) становится смешанным с заголовками. Я нашел другую альтернативу. CURL предоставляет опцию (CURLOPT_HEADERFUNCTION) для установки обратного вызова, который будет вызываться для каждой строки заголовка ответа. Функция будет получать объект curl и строку заголовка. Вы можете использовать код, подобный этому:

$cookies = Array();

$ch = curl_init('http://www.google.com/');

// Запросить обратный вызов.

curl_setopt($ch, CURLOPT_HEADERFUNCTION, "curlResponseHeaderCallback");

$result = curl_exec($ch);

var_dump($cookies);

function curlResponseHeaderCallback($ch, $headerLine) {

    global $cookies;

    if (preg_match('/^Set-Cookie:\s*([^;]*)/mi', $headerLine, $cookie) == 1)

        $cookies[] = $cookie;

    return strlen($headerLine); // Needed by curl

}

Это решение имеет недостаток в использовании глобальной переменной, но я думаю, что это не проблема для коротких скриптов. И вы всегда можете использовать статические методы и атрибуты, если curl оборачивается в класс.

 

Ответ 3

Этот код делает это без использования regexps, но требует расширения PECL HTTP.

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_HEADER, 1);

$result = curl_exec($ch);

curl_close($ch);

$headers = http_parse_headers($result);

$cookobjs = Array();

foreach($headers AS $k => $v){

    if (strtolower($k)=="set-cookie"){

        foreach($v AS $k2 => $v2){

            $cookobjs[] = http_parse_cookie($v2);

        }

    }

}

$cookies = Array();

foreach($cookobjs AS $row){

    $cookies[] = $row->cookies;

}

$tmp = Array();

// sort k=>v format

foreach($cookies AS $v){

    foreach ($v  AS $k1 => $v1){

        $tmp[$k1]=$v1;

    }

}

$cookies = $tmp;

print_r($cookies);

 

Ответ 4

hhb_curl_exec2 работает примерно как curl_exec, но arg3 это массив, который будет заполнен возвращаемыми http-заголовками (числовой индекс), arg4 массив, который будет заполнен возвращаемыми cookies ($cookies["expires"]=>"Fri, 06-May-2016 05:58:51 GMT"), а arg5 будет заполнен... информацией о сыром запросе, сделанном curl.

 

Недостатком является то, что он требует, чтобы CURLOPT_RETURNTRANSFER был включен, иначе он выдаст ошибку, и что он перезапишет CURLOPT_STDERR и CURLOPT_VERBOSE, если вы уже использовали их для чего-то еще... (возможно, я исправлю это позже). Пример использования:

<?php

header("content-type: text/plain;charset=utf8");

$ch=curl_init();

$headers=array();

$cookies=array();

$debuginfo="";

$body="";

curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);

curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);

$body=hhb_curl_exec2($ch,'https://www.youtube.com/',$headers,$cookies,$debuginfo);

var_dump('$cookies:',$cookies,'$headers:',$headers,'$debuginfo:',$debuginfo,'$body:',$body);

и сама функция...

function hhb_curl_exec2($ch, $url, &$returnHeaders = array(), &$returnCookies = array(), &$verboseDebugInfo = "") {

    $returnHeaders    = array();

    $returnCookies    = array();

    $verboseDebugInfo = "";

    if (!is_resource($ch) || get_resource_type($ch) !== 'curl') {

        throw new InvalidArgumentException('$ch must be a curl handle!');

    }

    if (!is_string($url)) {

        throw new InvalidArgumentException('$url must be a string!');

    }

    $verbosefileh = tmpfile();

    $verbosefile  = stream_get_meta_data($verbosefileh);

    $verbosefile  = $verbosefile['uri'];

    curl_setopt($ch, CURLOPT_VERBOSE, 1);

    curl_setopt($ch, CURLOPT_STDERR, $verbosefileh);

    curl_setopt($ch, CURLOPT_HEADER, 1);

    $html             = hhb_curl_exec($ch, $url);

    $verboseDebugInfo = file_get_contents($verbosefile);

    curl_setopt($ch, CURLOPT_STDERR, NULL);

    fclose($verbosefileh);

    unset($verbosefile, $verbosefileh);

    $headers       = array();

    $crlf          = "\x0d\x0a";

    $thepos        = strpos($html, $crlf . $crlf, 0);

    $headersString = substr($html, 0, $thepos);

    $headerArr     = explode($crlf, $headersString);

    $returnHeaders = $headerArr;

    unset($headersString, $headerArr);

    $htmlBody = substr($html, $thepos + 4); //should work on utf8/ascii headers... utf32? not so sure..

    unset($html);

    //I REALLY HOPE THERE EXIST A BETTER WAY TO GET COOKIES.. good grief this looks ugly..

    //at least it's tested and seems to work perfectly...

    $grabCookieName = function($str) {

        $ret = "";

        $i   = 0;

        for ($i = 0; $i < strlen($str); ++$i) {

            if ($str[$i] === ' ') {

                continue;

            }

            if ($str[$i] === '=') {

                break;

            }

            $ret .= $str[$i];

        }

        return urldecode($ret);

    };

    foreach ($returnHeaders as $header) {

        //Set-Cookie: crlfcoookielol=crlf+is%0D%0A+and+newline+is+%0D%0A+and+semicolon+is%3B+and+not+sure+what+else

        /*Set-Cookie:ci_spill=a%3A4%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22305d3d67b8016ca9661c3b032d4319df%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A14%3A%2285.164.158.128%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A109%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+WOW64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F43.0.2357.132+Safari%2F537.36%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1436874639%3B%7Dcab1dd09f4eca466660e8a767856d013; expires=Tue, 14-Jul-2015 13:50:39 GMT; path=/

        Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT;

        //Имена cookie не могут содержать ни одного из следующих '=,; \t\r\n\013\014'

        //

        */

        if (stripos($header, "Set-Cookie:") !== 0) {

            continue;

            /**/

        }

        $header = trim(substr($header, strlen("Set-Cookie:")));

        while (strlen($header) > 0) {

            $cookiename                 = $grabCookieName($header);

            $returnCookies[$cookiename] = '';

            $header                     = substr($header, strlen($cookiename) + 1); //also remove the = 

            if (strlen($header) < 1) {

                break;

            }

            ;

            $thepos = strpos($header, ';');

            if ($thepos === false) { //last cookie in this Set-Cookie.

                $returnCookies[$cookiename] = urldecode($header);

                break;

            }

            $returnCookies[$cookiename] = urldecode(substr($header, 0, $thepos));

            $header                     = trim(substr($header, $thepos + 1)); //also remove the ;

        }

    }

    unset($header, $cookiename, $thepos);

    return $htmlBody;

}

 

function hhb_curl_exec($ch, $url) {

    static $hhb_curl_domainCache = "";

    //$hhb_curl_domainCache=&$this->hhb_curl_domainCache;

    //$ch=&$this->curlh;

    if (!is_resource($ch) || get_resource_type($ch) !== 'curl') {

        throw new InvalidArgumentException('$ch must be a curl handle!');

    }

    if (!is_string($url)) {

        throw new InvalidArgumentException('$url must be a string!');

    }

    $tmpvar = "";

    if (parse_url($url, PHP_URL_HOST) === null) {

        if (substr($url, 0, 1) !== '/') {

            $url = $hhb_curl_domainCache . '/' . $url;

        } else {

            $url = $hhb_curl_domainCache . $url;

        }

    }

    ;

    curl_setopt($ch, CURLOPT_URL, $url);

    $html = curl_exec($ch);

    if (curl_errno($ch)) {

        throw new Exception('Curl error (curl_errno=' . curl_errno($ch) . ') on url ' . var_export($url, true) . ': ' . curl_error($ch));

        // echo 'Curl error: ' . curl_error($ch);

    }

    if ($html === '' && 203 != ($tmpvar = curl_getinfo($ch, CURLINFO_HTTP_CODE)) /*203 is "success, but no output"..*/ ) {

        throw new Exception('Curl returned nothing for ' . var_export($url, true) . ' but HTTP_RESPONSE_CODE was ' . var_export($tmpvar, true));

    }

    ;

    //помните, что curl (обычно) автоматически выполняет "Location: " http перенаправления...

    $hhb_curl_domainCache = parse_url(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL), PHP_URL_HOST);

    return $html;

}

 

Схожие статьи

Чек-листы оптимизации сайта, продвижения сайта и готовности к запуску
Web

Чек-листы оптимизации сайта, продвижения сайта и готовности к запуску

Web

Как предотвратить SQL-инъекцию в PHP?

Web

Как заменить URL-адреса в тексте ссылками HTML

Web

Получение разрешения экрана с помощью PHP