file_get_contents get Cookies

2019-04-17 12:06发布

I'm trying to develop a full PHP web browser that can handle cookies. I've created the following class:

<?php

class Browser
{
  private $cookies = '';
  private $response_cookies = '';
  private $content = '';

  /**
   * Cookie manager
   * @Description : To set or get cookies as Array or String
   */
  public function set_cookies_json($cookies)
  {
    $cookies_json = json_decode($cookies, true);
    $cookies_array = array();
    foreach ($cookies_json as $key => $value)
    {
      $cookies_array[] = $key .'='.$value;
    }
    $this->cookies = 'Cookie: ' . $cookies_array.join('; ') . "\r\n";
  }

  public function set_cookies_string($cookies)
  {
    $this->cookies = 'Cookie: ' . $cookies . "\r\n";
  }

  private function get_cookies()
  {
    global $http_response_header;
    $cookies_array = array();
    foreach($http_response_header as $s)
    {
      if (preg_match('|^Set-Cookie:\s*([^=]+)=([^;]+);(.+)$|', $s, $parts))
      {
        $cookies_array[] = $parts[1] . '=' . $parts[2];
      }
    }

    $this->cookies = 'Cookie: ' . $cookies_array.join('; ') . "\r\n";
  }

  /**
   * GET and POST request
   * Send a GET or a POST request to a remote URL
   */
  public function get($url)
  {
    $opts = array(
      'http' => array(
        'method' => 'GET',
        'header' => "Accept-language: en\r\n" .
                    $this->cookies
      )
    );
    $context = stream_context_create($opts);
    $this->content = file_get_contents($url, false, $context);
    $this->get_cookies();
    return $this->content;
  }

  public function post($url, $post_data)
  {
    $post_content = array();
    foreach ($post_data as $key => $value)
    {
      $post_content[] = $key .'='.$value;
    }

    $opts = array(
      'http' => array(
        'method' => 'GET',
        'header' => "Content-type: application/x-www-form-urlencoded\r\n" .
                    $this->cookies,
        'content' => $post_content.join('&'),
      )
    );
    $context = stream_context_create($opts);
    $this->content = file_get_contents($url, false, $context);
    $this->get_cookies();
    return $this->content;
  }
}

Basically, it can send a GET request and 'should' retrieve the cookies. I've made a very simple test script:

<?php

require('browser.class.php');

$browser = new Browser();
$browser->get('http://google.com');
print_r($browser->response_cookies);

But it fails on line 32 as $http_response_header looks to be null. Isn't it supposed to contain the header of my response ? I've read that page but it looks to work well for this guy : get cookie with file_get_contents in PHP

I know I could use cUrl to handle this but I'd really like to use a rough PHP code.

Did I make something wrong ?

Thanks for your precious help.

Edit:

Solution is:

<?php

class Browser
{
  public $request_cookies = '';
  public $response_cookies = '';
  public $content = '';

  /**
   * Cookie manager
   * @Description : To set or get cookies as Array or String
   */
  public function set_cookies_json($cookies)
  {
    $cookies_json = json_decode($cookies, true);
    $cookies_array = array();
    foreach ($cookies_json as $key => $value)
    {
      $cookies_array[] = $key .'='.$value;
    }
    $this->request_cookies = 'Cookie: ' . join('; ', $cookies_array) . "\r\n";
  }

  public function set_cookies_string($cookies)
  {
    $this->request_cookies = 'Cookie: ' . $cookies . "\r\n";
  }

  private function get_cookies($http_response_header)
  {
    $cookies_array = array();
    foreach($http_response_header as $s)
    {
      if (preg_match('|^Set-Cookie:\s*([^=]+)=([^;]+);(.+)$|', $s, $parts))
      {
        $cookies_array[] = $parts[1] . '=' . $parts[2];
      }
    }

    $this->response_cookies = 'Cookie: ' . join('; ', $cookies_array) . "\r\n";
  }

  /**
   * GET and POST request
   * Send a GET or a POST request to a remote URL
   */
  public function get($url)
  {
    $opts = array(
      'http' => array(
        'method' => 'GET',
        'header' => "Accept-language: en\r\n" .
                    $this->request_cookies
      )
    );
    $context = stream_context_create($opts);
    $this->content = file_get_contents($url, false, $context);
    $this->get_cookies($http_response_header);
    return $this->content;
  }

  public function post($url, $post_data)
  {
    $post_content = array();
    foreach ($post_data as $key => $value)
    {
      $post_content[] = $key .'='.$value;
    }

    $opts = array(
      'http' => array(
        'method' => 'GET',
        'header' => "Content-type: application/x-www-form-urlencoded\r\n" .
                    $this->request_cookies,
        'content' => join('&', $post_content),
      )
    );
    $context = stream_context_create($opts);
    $this->content = file_get_contents($url, false, $context);
    $this->get_cookies($http_response_header);
    return $this->content;
  }
}

1条回答
淡お忘
2楼-- · 2019-04-17 12:53

According to php.net:

$http_response_header will be created in the local scope.

Because of this $http_response_header is available only in the scope of get(). You can pass it like $this->get_cookies($http_response_header); or create a property to store it.

查看更多
登录 后发表回答