vendor/nategood/httpful/src/Httpful/Response.php line 34

Open in your IDE?
  1. <?php
  2. namespace Httpful;
  3. /**
  4.  * Models an HTTP response
  5.  *
  6.  * @author Nate Good <me@nategood.com>
  7.  */
  8. class Response
  9. {
  10.     public $body,
  11.            $raw_body,
  12.            $headers,
  13.            $raw_headers,
  14.            $request,
  15.            $code 0,
  16.            $content_type,
  17.            $parent_type,
  18.            $charset,
  19.            $meta_data,
  20.            $is_mime_vendor_specific false,
  21.            $is_mime_personal false;
  22.     private $parsers;
  23.     /**
  24.      * @param string $body
  25.      * @param string $headers
  26.      * @param Request $request
  27.      * @param array $meta_data
  28.      */
  29.     public function __construct($body$headersRequest $request, array $meta_data = array())
  30.     {
  31.         $this->request      $request;
  32.         $this->raw_headers  $headers;
  33.         $this->raw_body     $body;
  34.         $this->meta_data    $meta_data;
  35.         $this->code         $this->_parseCode($headers);
  36.         $this->headers      Response\Headers::fromString($headers);
  37.         $this->_interpretHeaders();
  38.         $this->body         $this->_parse($body);
  39.     }
  40.     /**
  41.      * Status Code Definitions
  42.      *
  43.      * Informational 1xx
  44.      * Successful    2xx
  45.      * Redirection   3xx
  46.      * Client Error  4xx
  47.      * Server Error  5xx
  48.      *
  49.      * http://pretty-rfc.herokuapp.com/RFC2616#status.codes
  50.      *
  51.      * @return bool Did we receive a 4xx or 5xx?
  52.      */
  53.     public function hasErrors()
  54.     {
  55.         return $this->code >= 400;
  56.     }
  57.     /**
  58.      * @return bool
  59.      */
  60.     public function hasBody()
  61.     {
  62.         return !empty($this->body);
  63.     }
  64.     /**
  65.      * Parse the response into a clean data structure
  66.      * (most often an associative array) based on the expected
  67.      * Mime type.
  68.      * @param string Http response body
  69.      * @return array|string|object the response parse accordingly
  70.      */
  71.     public function _parse($body)
  72.     {
  73.         // If the user decided to forgo the automatic
  74.         // smart parsing, short circuit.
  75.         if (!$this->request->auto_parse) {
  76.             return $body;
  77.         }
  78.         // If provided, use custom parsing callback
  79.         if (isset($this->request->parse_callback)) {
  80.             return call_user_func($this->request->parse_callback$body);
  81.         }
  82.         // Decide how to parse the body of the response in the following order
  83.         //  1. If provided, use the mime type specifically set as part of the `Request`
  84.         //  2. If a MimeHandler is registered for the content type, use it
  85.         //  3. If provided, use the "parent type" of the mime type from the response
  86.         //  4. Default to the content-type provided in the response
  87.         $parse_with $this->request->expected_type;
  88.         if (empty($this->request->expected_type)) {
  89.             $parse_with Httpful::hasParserRegistered($this->content_type)
  90.                 ? $this->content_type
  91.                 $this->parent_type;
  92.         }
  93.        return Httpful::get($parse_with)->parse($body);
  94.     }
  95.     /**
  96.      * Parse text headers from response into
  97.      * array of key value pairs
  98.      * @param string $headers raw headers
  99.      * @return array parse headers
  100.      */
  101.     public function _parseHeaders($headers)
  102.     {
  103.         $headers preg_split("/(\r|\n)+/"$headers, -1\PREG_SPLIT_NO_EMPTY);
  104.         $parse_headers = array();
  105.         for ($i 1$i count($headers); $i++) {
  106.             list($key$raw_value) = explode(':'$headers[$i], 2);
  107.             $key trim($key);
  108.             $value trim($raw_value);
  109.             if (array_key_exists($key$parse_headers)) {
  110.                 // See HTTP RFC Sec 4.2 Paragraph 5
  111.                 // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
  112.                 // If a header appears more than once, it must also be able to
  113.                 // be represented as a single header with a comma-separated
  114.                 // list of values.  We transform accordingly.
  115.                 $parse_headers[$key] .= ',' $value;
  116.             } else {
  117.                 $parse_headers[$key] = $value;
  118.             }
  119.         }
  120.         return $parse_headers;
  121.     }
  122.     public function _parseCode($headers)
  123.     {
  124.         $end strpos($headers"\r\n");
  125.         if ($end === false$end strlen($headers);
  126.         $parts explode(' 'substr($headers0$end));
  127.         if (count($parts) < || !is_numeric($parts[1])) {
  128.             throw new \Exception("Unable to parse response code from HTTP response due to malformed response");
  129.         }
  130.         return intval($parts[1]);
  131.     }
  132.     /**
  133.      * After we've parse the headers, let's clean things
  134.      * up a bit and treat some headers specially
  135.      */
  136.     public function _interpretHeaders()
  137.     {
  138.         // Parse the Content-Type and charset
  139.         $content_type = isset($this->headers['Content-Type']) ? $this->headers['Content-Type'] : '';
  140.         $content_type explode(';'$content_type);
  141.         $this->content_type $content_type[0];
  142.         if (count($content_type) == && strpos($content_type[1], '=') !== false) {
  143.             list($nill$this->charset) = explode('='$content_type[1]);
  144.         }
  145.         // RFC 2616 states "text/*" Content-Types should have a default
  146.         // charset of ISO-8859-1. "application/*" and other Content-Types
  147.         // are assumed to have UTF-8 unless otherwise specified.
  148.         // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7.1
  149.         // http://www.w3.org/International/O-HTTP-charset.en.php
  150.         if (!isset($this->charset)) {
  151.             $this->charset substr($this->content_type5) === 'text/' 'iso-8859-1' 'utf-8';
  152.         }
  153.         // Is vendor type? Is personal type?
  154.         if (strpos($this->content_type'/') !== false) {
  155.             list($type$sub_type) = explode('/'$this->content_type);
  156.             $this->is_mime_vendor_specific substr($sub_type04) === 'vnd.';
  157.             $this->is_mime_personal substr($sub_type04) === 'prs.';
  158.         }
  159.         // Parent type (e.g. xml for application/vnd.github.message+xml)
  160.         $this->parent_type $this->content_type;
  161.         if (strpos($this->content_type'+') !== false) {
  162.             list($vendor$this->parent_type) = explode('+'$this->content_type2);
  163.             $this->parent_type Mime::getFullMime($this->parent_type);
  164.         }
  165.     }
  166.     /**
  167.      * @return string
  168.      */
  169.     public function __toString()
  170.     {
  171.         return $this->raw_body;
  172.     }
  173. }