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:

  1. function curl_get_contents($url, $headers = array(), $maxredirs = 0) { 
  2.     static $ch, $redirscount = 0; 
  3.     $ch or $ch = curl_init(); 
  4.     curl_setopt($ch, CURLOPT_URL, $url); 
  5.     curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 
  6.     curl_setopt($ch, CURLOPT_ENCODING, 'gzip, deflate'); 
  7.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
  8.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
  9.     curl_setopt($ch, CURLOPT_TIMEOUT, 10); 
  10.     $contents = curl_exec($ch); 
  11.     $redir    = curl_getinfo($ch, CURLINFO_REDIRECT_URL); 
  12.     if ($redir && $redir != $url && ($maxredirs < 0 || $redirscount < $maxredirs)) { 
  13.         $redirscount++; 
  14.         $headers['Referer'] = 'Referer: ' . $url; 
  15.         return curl_get_contents($redir, $headers, $maxredirs); 
  16.     } else { 
  17.         curl_close($ch); 
  18.         $ch = $redirscount = 0; 
  19.         return $contents; 
  20.     } 
  21. } 

Berikut adalah fungsi kompatibel untuk PHP versi lama. Mungkin PHP >= 4.0.2. Namun hanya saya uji pada PHP 5.2.x:

  1. function curl_get_contents_compat($url, $headers = array(), $maxredirs = 0) { 
  2.     static $ch, $redirscount = 0; 
  3.     $ch or $ch = curl_init(); 
  4.     curl_setopt($ch, CURLOPT_URL, $url); 
  5.     curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 
  6.     curl_setopt($ch, CURLOPT_ENCODING, 'gzip, deflate'); 
  7.     curl_setopt($ch, CURLOPT_HEADER, true); 
  8.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
  9.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
  10.     curl_setopt($ch, CURLOPT_TIMEOUT, 10); 
  11.     $contents = curl_exec($ch); 
  12.     $first    = true; 
  13.     $redir    = $body = null; 
  14.     $tok      = strtok($contents, "\n"); 
  15.     while ($tok !== false) { 
  16.         $tok = rtrim($tok); 
  17.         if ($first && !$tok) { 
  18.             $body  = null; 
  19.             $first = false; 
  20.         } elseif ($first && strpos($tok, 'Location: ') === 0) { 
  21.             $redir = str_replace('Location: ', null, $tok); 
  22.             $body  = null; 
  23.             break; 
  24.         } else { 
  25.             $body .= $tok . "\n"; 
  26.         } 
  27.         $tok = strtok("\n"); 
  28.     } 
  29.     if ($redir && $redir != $url && ($maxredirs < 0 || $redirscount < $maxredirs)) { 
  30.         $redirscount++; 
  31.         $headers['Referer'] = 'Referer: ' . $url; 
  32.         if (strpos($redir, '://') === false) { // relative url 
  33.             $path_pos = strpos($url, '/', 8); 
  34.             if ($redir[0] == '/') { 
  35.                 $redir = substr($url, 0, $path_pos) . $redir; 
  36.             } else { 
  37.                 $path = substr(strtok($url, '?'), $path_pos); 
  38.                 $url  = substr($url, 0, $path_pos) . '/'; 
  39.                 if (strpos(basename($path), '.') === false) { 
  40.                     $url .= ltrim($path, '/'); 
  41.                 } else { 
  42.                     $url .= ltrim(substr($path, 0, strrpos($path, '/')), '/'); 
  43.                 } 
  44.                 $redir = rtrim($url, '/') . '/' . $redir; 
  45.             } 
  46.         } 
  47.         return curl_get_contents_compat($redir, $headers, $maxredirs); 
  48.     } else { 
  49.         curl_close($ch); 
  50.         $ch = $redirscount = 0; 
  51.         return $body; 
  52.     } 
  53. } 

Berikut adalah fungsi wrapper yang akan otomatis menyesuaikan:

  1. function get_contents($url, $headers = array(), $maxredirs = 0) { 
  2.     return defined('CURLINFO_REDIRECT_URL') ? curl_get_contents($url, $headers, $maxredirs) 
  3.                                             : curl_get_contents_compat($url, $headers, $maxredirs); 
  4. } 

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

Contoh:

http://localhost/target.php
  1. <?php 
  2.  
  3. header('Location: http://localhost/target1.php'); 

http://localhost/target1.php
  1. <?php 
  2.  
  3. header('Location: http://localhost/target2.php'); 

http://localhost/target2.php
  1. <?php 
  2.  
  3. phpinfo(); 

http://localhost/test.php
  1. <?php 
  2.  
  3. // Paste tiga fungsi diatas ke sini 
  4.  
  5. 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
  1. <?php 
  2.  
  3. // Paste tiga fungsi diatas ke sini 
  4.  
  5. $headers   = array(); 
  6. $headers[] = 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0'; 
  7. $headers[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'; 
  8. $headers[] = 'Accept-Language: en-US,en;q=0.5'; 
  9. echo get_contents('http://localhost/target.php', $headers); 

Selalu cek halaman ini karena selalu diperbaharui.

Update: Silahkan cek github saya: https://github.com/nggit/php-simple-client