| 
						 | 
						- <?php
 - namespace p3k;
 - 
 - class HTTPStream {
 - 
 -   public $timeout = 4;
 -   public $max_redirects = 8;
 - 
 -   public static function exception_error_handler($severity, $message, $file, $line) {
 -     if (!(error_reporting() & $severity)) {
 -       // This error code is not included in error_reporting
 -       return;
 -     }
 -     throw new \ErrorException($message, 0, $severity, $file, $line);
 -   }
 - 
 -   public function get($url, $headers=[]) {
 -     set_error_handler("p3k\HTTPStream::exception_error_handler");
 -     $context = $this->_stream_context('GET', $url, false, $headers);
 -     return $this->_fetch($url, $context);
 -   }
 - 
 -   public function post($url, $body, $headers=[]) {
 -     set_error_handler("p3k\HTTPStream::exception_error_handler");
 -     $context = $this->_stream_context('POST', $url, $body, $headers);
 -     return $this->_fetch($url, $context);
 -   }
 - 
 -   public function head($url) {
 -     set_error_handler("p3k\HTTPStream::exception_error_handler");
 -     $context = $this->_stream_context('HEAD', $url);
 -     return $this->_fetch($url, $context);
 -   }
 - 
 -   private function _fetch($url, $context) {
 -     $error = false;
 - 
 -     try {
 -       $body = file_get_contents($url, false, $context);
 -       // This sets $http_response_header
 -       // see http://php.net/manual/en/reserved.variables.httpresponseheader.php
 -     } catch(\Exception $e) {
 -       $body = false;
 -       $http_response_header = [];
 -       $description = str_replace('file_get_contents(): ', '', $e->getMessage());
 -       $code = 'unknown';
 - 
 -       if(preg_match('/getaddrinfo failed/', $description)) {
 -         $code = 'dns_error';
 -         $description = str_replace('php_network_getaddresses: ', '', $description);
 -       }
 - 
 -       if(preg_match('/timed out|request failed/', $description)) {
 -         $code = 'timeout';
 -       }
 - 
 -       if(preg_match('/certificate/', $description)) {
 -         $code = 'ssl_error';
 -       }
 - 
 -       $error = [
 -         'description' => $description,
 -         'code' => $code
 -       ];
 -     }
 - 
 -     return array(
 -       'code' => self::parse_response_code($http_response_header),
 -       'headers' => self::parse_headers($http_response_header),
 -       'body' => $body,
 -       'error' => $error ? $error['code'] : false,
 -       'error_description' => $error ? $error['description'] : false,
 -       'url' => $url,
 -     );
 -   }
 - 
 -   private function _stream_context($method, $url, $body=false, $headers=[]) {
 -     $options = [
 -       'method' => $method,
 -       'timeout' => $this->timeout,
 -       'ignore_errors' => true,
 -     ];
 - 
 -     if($body) {
 -       $options['content'] = $body;
 -     }
 - 
 -     if($headers) {
 -       $options['header'] = implode("\r\n", $headers);
 -     }
 - 
 -     // Special-case appspot.com URLs to not follow redirects.
 -     // https://cloud.google.com/appengine/docs/php/urlfetch/
 -     if(should_follow_redirects($url)) {
 -       $options['follow_location'] = 1;
 -       $options['max_redirects'] = $this->max_redirects;
 -     } else {
 -       $options['follow_location'] = 0;
 -     }
 - 
 -     return stream_context_create(['http' => $options]);
 -   }
 - 
 -   public static function parse_response_code($headers) {
 -     // When a response is a redirect, we want to find the last occurrence of the HTTP code
 -     $code = false;
 -     foreach($headers as $field) {
 -       if(preg_match('/HTTP\/\d\.\d (\d+)/', $field, $match)) {
 -         $code = $match[1];
 -       }
 -     }    
 -     return $code;
 -   }
 - 
 -   public static function parse_headers($headers) {
 -     $retVal = array();
 -     foreach($headers as $field) {
 -       if(preg_match('/([^:]+): (.+)/m', $field, $match)) {
 -         $match[1] = preg_replace_callback('/(?<=^|[\x09\x20\x2D])./', function($m) {
 -           return strtoupper($m[0]);
 -         }, strtolower(trim($match[1])));
 -         // If there's already a value set for the header name being returned, turn it into an array and add the new value
 -         $match[1] = preg_replace_callback('/(?<=^|[\x09\x20\x2D])./', function($m) {
 -           return strtoupper($m[0]);
 -         }, strtolower(trim($match[1])));
 -         if(isset($retVal[$match[1]])) {
 -           if(!is_array($retVal[$match[1]]))
 -             $retVal[$match[1]] = array($retVal[$match[1]]);
 -           $retVal[$match[1]][] = $match[2];
 -         } else {
 -           $retVal[$match[1]] = trim($match[2]);
 -         }
 -       }
 -     }
 -     return $retVal;
 -   }
 - 
 - }
 
 
  |