[ Normal ]

PHP cURL Redirect Tanpa Opsi FOLLOWLOCATION

Tidak seperti file_get_contents(), standarnya cURL di PHP tidak mengikuti redirect (pengalihan halaman). Harus mengaktifkan CURLOPT_FOLLOWLOCATION agar bisa mengikuti redirect. Namun tidak semua hosting menggunakan konfigurasi yang mengijinkan fitur ini. Seperti saat safe_mode atau open_basedir diaktifkan karena alasan keamanan. Untuk itu saya mencoba menulis fungsi berikut untuk mengatasi hal ini.

Berikut adalah fungsi untuk PHP >= 5.3.7 karena konstan CURLINFO_REDIRECT_URL tersedia sejak versi tersebut:
function curl_get_contents($url, $headers = array(), $maxredirs = 0) {
    static $ch, $redir, $redirscount = 0;
    $ch or $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_ENCODING, 'gzip, deflate');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    $contents = curl_exec($ch);
    $redir    = curl_getinfo($ch, CURLINFO_REDIRECT_URL);
    if ((!$maxredirs || $redirscount < $maxredirs) && $redir && $redir !== $url) {
        $redirscount++;
        $headers['REFERER'] = 'Referer: '.$url;
        return curl_get_contents($redir, $headers, $maxredirs);
    }
    else {
        $redirscount = 0;
        curl_close($ch);
        return $contents;
    }
}


Berikut adalah fungsi kompatibel untuk PHP versi lama. Mungkin PHP >= 4.0.2. Namun hanya saya uji pada PHP 5.2.x:
function curl_get_contents_compat($url, $headers = array(), $maxredirs = 0) {
    static $ch, $redir, $redirscount = 0;
    $ch or $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_ENCODING, 'gzip, deflate');
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    $contents = curl_exec($ch);
    $body     = null;
    $once     = true;
    $tok      = strtok($contents, "\n");
    while ($tok !== false) {
        $tok = rtrim($tok);
        if ($once && !$tok) {
            $body = null;
            $once = false;
        }
        elseif ($once && strpos($tok, 'Location: ') === 0) {
            $redir = str_replace('Location: ', null, $tok);
            $body  = null;
            break;
        }
        else {
            $body .= $tok."\n";
        }
        $tok = strtok("\n");
    }
    if ((!$maxredirs || $redirscount < $maxredirs) && $redir && $redir !== $url) {
        $redirscount++;
        $headers['REFERER'] = 'Referer: '.$url;
        return curl_get_contents_compat($redir, $headers, $maxredirs);
    }
    else {
        $redirscount = 0;
        curl_close($ch);
        return $body;
    }
}


Berikut adalah fungsi wrapper yang akan otomatis menyesuaikan:
function get_contents($url, $headers = array(), $maxredirs = 0) {
    return defined('CURLINFO_REDIRECT_URL') ? curl_get_contents($url, $headers, $maxredirs)
                                            : curl_get_contents_compat($url, $headers, $maxredirs);
}

Penggunaan:
Argumen pertama adalah wajib. Sisanya opsional.
$maxredirs standar nilainya 0, berarti redirect tak terbatas.

Contoh:
http://localhost/target.php
<?php

header('Location: http://localhost/target1.php');


http://localhost/target1.php
<?php

header('Location: http://localhost/target2.php');


http://localhost/target2.php
<?php

phpinfo();


http://localhost/test.php
<?php

// Paste tiga fungsi diatas ke sini

echo get_contents('http://localhost/target.php');


Jika ingin membuat cURL benar-benar terdeteksi seperti browser tertentu, bisa menambahkan opsi $headers yang berupa array:
http://localhost/test.php
<?php

// Paste tiga fungsi diatas ke sini

$headers   = array();
$headers[] = 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0';
$headers[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
$headers[] = 'Accept-Language: en-US,en;q=0.5';
$headers[] = 'Connection: keep-alive';
echo get_contents('http://localhost/target.php', $headers);


Selalu cek halaman ini karena selalu diperbaharui.