Çerezleri bir php curl'den bir değişkene nasıl alırım


126

Bu nedenle, başka bir şirketteki bir adam, soap veya xml-rpc veya rest veya başka herhangi bir makul iletişim protokolü kullanmak yerine, tüm yanıtını başlıkta çerezler olarak yerleştirmesinin harika olacağını düşündü.

Bu çerezleri umarım bu curl yanıtından bir dizi olarak çıkarmam gerekir. Hayatımın bir kısmını bunun için bir ayrıştırıcı yazarak harcamak zorunda kalırsam çok mutsuz olacağım.

Bunun, tercihen bir dosyaya hiçbir şey yazmadan nasıl basitçe yapılabileceğini bilen var mı?

Bu konuda bana yardım edebilecek biri olursa çok minnettar olacağım.

Yanıtlar:


174
$ch = curl_init('http://www.google.com/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// get headers too with this line
curl_setopt($ch, CURLOPT_HEADER, 1);
$result = curl_exec($ch);
// get cookie
// multi-cookie variant contributed by @Combuster in comments
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);

31
Maalesef bunun doğru cevap olduğuna dair bir his var. Bence curl'nin bana eşlenmiş bir dizi verememesi çok saçma.
susuz93

3
Sana vereceğim ama preg_match yanlıştı. Sadece seansı istemedim, neden böyle düşündüğünü anladım. Ancak, sistemini oluşturan dahi, çerezi bir alma veya postadaki gibi tam bir yanıt haritasıyla yüklüyor. Şunun gibi bir şey: Set-Cookie: price = 1 Set-Cookie: status = kabul '/ ^ Set-Cookie: (. *?) = (. *?) $ /
Sm

7
@ susuz93 Curl size eşlenmiş bir dizi veremez. Ama size onu kurtarmanın bir yolunu gösteriyorcurl_setopt($ch, CURLOPT_HEADERFUNCTION, 'callback_SaveHeaders');
Shiplu Mokaddim

2
Döndürülen tanımlama bilgisi yapısına bağlı olarak, son satırın parse_str($m[1], $cookies), örneğin tanımlama bilgilerini $cookiesdeğişkendeki ilişkilendirilebilir diziye
dolduracak

7
Birden fazla çerez alan birleşik düzeltmeler için: 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); }
Combuster

39

Bu soru oldukça eski olmasına ve kabul edilen yanıt geçerli olmasına rağmen, HTTP yanıtının içeriği (HTML, XML, JSON, ikili veya her neyse) başlıklarla karıştığı için biraz rahatsızlık duyuyorum.

Farklı bir alternatif buldum. CURL, CURLOPT_HEADERFUNCTIONher yanıt başlık satırı için çağrılacak bir geri arama ayarlama seçeneği ( ) sağlar . İşlev, curl nesnesini ve başlık satırına sahip bir dizeyi alır.

Bunun gibi bir kod kullanabilirsiniz (TML yanıtından uyarlanmıştır):

$cookies = Array();
$ch = curl_init('http://www.google.com/');
// Ask for the callback.
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
}

Bu çözümün global bir değişken kullanma dezavantajı var ama sanırım bu kısa betikler için bir sorun değil. Ve curl bir sınıfa sarılıyorsa her zaman statik yöntemler ve öznitelikleri kullanabilirsiniz.


10
Global yerine, referans tutan bir kapanış kullanabilirsiniz $cookies. $curlResponseHeaderCallback = function ($ch, $headerLine) use (&$cookies) {sonra curl_setopt($ch, CURLOPT_HEADERFUNCTION, $curlResponseHeaderCallback);.
Seph

Bunların hepsi bir sınıfta olursa ne olur? Sınıf işlevine nasıl başvurursunuz $class->curlResponseHeaderCallback()? Yoksa curlResponseHeaderCallbacksınıfın dışında mı yapıyorsun ?
Yedinci

13

Bu, normal ifadeler olmadan yapar, ancak PECL HTTP uzantısını gerektirir .

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);

2
Bunun için teşekkürler. Açık, anlamsal bir çözüm, bir uzantı yükleme zahmetine değer.
Ben Jacobs

2
pecl installGerçekten işe yarasaydı bu en iyi çözüm olurdu . Grrr.
Robin Winslow

11

CURLOPT_COOKIE_FILE kullanırsanız ve CURLOPT_COOKIE_JAR curl çerezleri bir dosyadan / dosyadan okuyacak / yazacaktır. Curl bittikten sonra istediğiniz gibi okuyabilir ve / veya değiştirebilirsiniz.


12
Bence amaç bu dosyayı kullanmak değil
Nicolas Thery

3

libcurl ayrıca bilinen tüm tanımlama bilgilerini çıkaran CURLOPT_COOKIELIST sağlar. İhtiyacınız olan tek şey, PHP / CURL bağlamanın onu kullanabileceğinden emin olmaktır.


12
PHP API aracılığıyla kullanılamaz.
Emre Yazıcı

1

buradaki biri onu faydalı bulabilir. hhb_curl_exec2, curl_exec'e çok benzer şekilde çalışır, ancak arg3, döndürülen http başlıklarıyla (sayısal dizin) doldurulacak bir dizidir ve arg4, döndürülen çerezlerle doldurulacak bir dizidir ($ çerezler ["sona erer"] => " Cum, 06-Mayıs-2016 05:58:51 GMT ") ve arg5, curl tarafından yapılan ham istek hakkında ... bilgi ile doldurulacaktır.

dezavantajı, CURLOPT_RETURNTRANSFER'ın açık olmasını gerektirmesi, aksi takdirde hata vermesi ve bunları zaten başka bir şey için kullanıyorsanız CURLOPT_STDERR ve CURLOPT_VERBOSE'un üzerine yazmasıdır .. (bunu daha sonra düzeltebilirim)

nasıl kullanılacağına dair örnek:

<?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);

ve işlevin kendisi ..

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 names cannot contain any of the following '=,; \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));
    }
    ;
    //remember that curl (usually) auto-follows the "Location: " http redirects..
    $hhb_curl_domainCache = parse_url(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL), PHP_URL_HOST);
    return $html;
}

1

Kabul edilen yanıt, tüm yanıt mesajını arayacak gibi görünüyor. "Set-Cookie" kelimesi bir satırın başındaysa, bu size tanımlama bilgisi başlıkları için yanlış eşleşmeler verebilir. Çoğu durumda iyi olması gerekirken. Daha güvenli yol, mesajın başından itibaren mesaj başlıklarının sonunu gösteren ilk boş satıra kadar okumak olabilir. Bu, ilk boş satırı aramalı ve sonra bu satırlarda yalnızca "Set-Cookie" yi bulmak için preg_grep kullanmalı alternatif bir çözümdür.

    curl_setopt($ch, CURLOPT_HEADER, 1);
    //Return everything
    $res = curl_exec($ch);
    //Split into lines
    $lines = explode("\n", $res);
    $headers = array();
    $body = "";
    foreach($lines as $num => $line){
        $l = str_replace("\r", "", $line);
        //Empty line indicates the start of the message body and end of headers
        if(trim($l) == ""){
            $headers = array_slice($lines, 0, $num);
            $body = $lines[$num + 1];
            //Pull only cookies out of the headers
            $cookies = preg_grep('/^Set-Cookie:/', $headers);
            break;
        }
    }

1
Kabul edilen yanıt, tüm yanıt mesajını arayacak gibi görünüyor. "Set-Cookie" kelimesi bir satırın başındaysa, bu size tanımlama bilgisi başlıkları için yanlış eşleşmeler verebilir. Çoğu durumda iyi olması gerekirken. Daha güvenli yol, mesajın başından itibaren mesaj başlıklarının sonunu gösteren ilk boş satıra kadar okumak olabilir. Bu, ilk boş satırı aramalı ve sonra bu satırlarda yalnızca "Set-Cookie" yi bulmak için preg_grep kullanmalı alternatif bir çözümdür.
Rich Wandell

0

Anladığım kadarıyla, çerezlerin curlbir dosyaya ( curl -c cookie_file) yazılması gerekiyor . Eğer çalıştırıyorsanız curlPHP'nin aracılığıyla execveya systemfonksiyonları (veya bu ailede bir şey) oluşturduktan sonra, bir dosyaya çerezleri kaydetmek dosyayı açmak ve bunları okumak mümkün olmalıdır.


4
Neredeyse kesinlikle php.net/curl'den bahsediyor :)
TML
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.