Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Response.php
Go to the documentation of this file.
1 <?php
2 
27 #require_once 'Zend/Http/Header/HeaderValue.php';
28 
40 {
47  protected static $messages = array(
48  // Informational 1xx
49  100 => 'Continue',
50  101 => 'Switching Protocols',
51 
52  // Success 2xx
53  200 => 'OK',
54  201 => 'Created',
55  202 => 'Accepted',
56  203 => 'Non-Authoritative Information',
57  204 => 'No Content',
58  205 => 'Reset Content',
59  206 => 'Partial Content',
60 
61  // Redirection 3xx
62  300 => 'Multiple Choices',
63  301 => 'Moved Permanently',
64  302 => 'Found', // 1.1
65  303 => 'See Other',
66  304 => 'Not Modified',
67  305 => 'Use Proxy',
68  // 306 is deprecated but reserved
69  307 => 'Temporary Redirect',
70 
71  // Client Error 4xx
72  400 => 'Bad Request',
73  401 => 'Unauthorized',
74  402 => 'Payment Required',
75  403 => 'Forbidden',
76  404 => 'Not Found',
77  405 => 'Method Not Allowed',
78  406 => 'Not Acceptable',
79  407 => 'Proxy Authentication Required',
80  408 => 'Request Timeout',
81  409 => 'Conflict',
82  410 => 'Gone',
83  411 => 'Length Required',
84  412 => 'Precondition Failed',
85  413 => 'Request Entity Too Large',
86  414 => 'Request-URI Too Long',
87  415 => 'Unsupported Media Type',
88  416 => 'Requested Range Not Satisfiable',
89  417 => 'Expectation Failed',
90 
91  // Server Error 5xx
92  500 => 'Internal Server Error',
93  501 => 'Not Implemented',
94  502 => 'Bad Gateway',
95  503 => 'Service Unavailable',
96  504 => 'Gateway Timeout',
97  505 => 'HTTP Version Not Supported',
98  509 => 'Bandwidth Limit Exceeded'
99  );
100 
106  protected $version;
107 
113  protected $code;
114 
121  protected $message;
122 
128  protected $headers = array();
129 
135  protected $body;
136 
156  public function __construct($code, array $headers, $body = null, $version = '1.1', $message = null)
157  {
158  // Make sure the response code is valid and set it
159  if (self::responseCodeAsText($code) === null) {
160  #require_once 'Zend/Http/Exception.php';
161  throw new Zend_Http_Exception("{$code} is not a valid HTTP response code");
162  }
163 
164  $this->code = $code;
165 
166  foreach ($headers as $name => $value) {
167  if (is_int($name)) {
168  $header = explode(":", $value, 2);
169  if (count($header) != 2) {
170  #require_once 'Zend/Http/Exception.php';
171  throw new Zend_Http_Exception("'{$value}' is not a valid HTTP header");
172  }
173 
174  $name = trim($header[0]);
175  $value = trim($header[1]);
176  }
177 
178  $this->headers[ucwords(strtolower($name))] = $value;
179  }
180 
181  // Set the body
182  $this->body = $body;
183 
184  // Set the HTTP version
185  if (! preg_match('|^\d\.\d$|', $version)) {
186  #require_once 'Zend/Http/Exception.php';
187  throw new Zend_Http_Exception("Invalid HTTP response version: $version");
188  }
189 
190  $this->version = $version;
191 
192  // If we got the response message, set it. Else, set it according to
193  // the response code
194  if (is_string($message)) {
195  $this->message = $message;
196  } else {
197  $this->message = self::responseCodeAsText($code);
198  }
199  }
200 
206  public function isError()
207  {
208  $restype = floor($this->code / 100);
209  if ($restype == 4 || $restype == 5) {
210  return true;
211  }
212 
213  return false;
214  }
215 
221  public function isSuccessful()
222  {
223  $restype = floor($this->code / 100);
224  if ($restype == 2 || $restype == 1) { // Shouldn't 3xx count as success as well ???
225  return true;
226  }
227 
228  return false;
229  }
230 
236  public function isRedirect()
237  {
238  $restype = floor($this->code / 100);
239  if ($restype == 3) {
240  return true;
241  }
242 
243  return false;
244  }
245 
258  public function getBody()
259  {
260  $body = '';
261 
262  // Decode the body if it was transfer-encoded
263  switch (strtolower($this->getHeader('transfer-encoding'))) {
264 
265  // Handle chunked body
266  case 'chunked':
267  $body = self::decodeChunkedBody($this->body);
268  break;
269 
270  // No transfer encoding, or unknown encoding extension:
271  // return body as is
272  default:
273  $body = $this->body;
274  break;
275  }
276 
277  // Decode any content-encoding (gzip or deflate) if needed
278  switch (strtolower($this->getHeader('content-encoding'))) {
279 
280  // Handle gzip encoding
281  case 'gzip':
283  break;
284 
285  // Handle deflate encoding
286  case 'deflate':
288  break;
289 
290  default:
291  break;
292  }
293 
294  return $body;
295  }
296 
305  public function getRawBody()
306  {
307  return $this->body;
308  }
309 
315  public function getVersion()
316  {
317  return $this->version;
318  }
319 
325  public function getStatus()
326  {
327  return $this->code;
328  }
329 
336  public function getMessage()
337  {
338  return $this->message;
339  }
340 
346  public function getHeaders()
347  {
348  return $this->headers;
349  }
350 
357  public function getHeader($header)
358  {
359  $header = ucwords(strtolower($header));
360  if (! is_string($header) || ! isset($this->headers[$header])) return null;
361 
362  return $this->headers[$header];
363  }
364 
372  public function getHeadersAsString($status_line = true, $br = "\n")
373  {
374  $str = '';
375 
376  if ($status_line) {
377  $str = "HTTP/{$this->version} {$this->code} {$this->message}{$br}";
378  }
379 
380  // Iterate over the headers and stringify them
381  foreach ($this->headers as $name => $value)
382  {
383  if (is_string($value))
384  $str .= "{$name}: {$value}{$br}";
385 
386  elseif (is_array($value)) {
387  foreach ($value as $subval) {
388  $str .= "{$name}: {$subval}{$br}";
389  }
390  }
391  }
392 
393  return $str;
394  }
395 
402  public function asString($br = "\r\n")
403  {
404  return $this->getHeadersAsString(true, $br) . $br . $this->getRawBody();
405  }
406 
412  public function __toString()
413  {
414  return $this->asString();
415  }
416 
429  public static function responseCodeAsText($code = null, $http11 = true)
430  {
432  if (! $http11) $messages[302] = 'Moved Temporarily';
433 
434  if ($code === null) {
435  return $messages;
436  } elseif (isset($messages[$code])) {
437  return $messages[$code];
438  } else {
439  return 'Unknown';
440  }
441  }
442 
449  public static function extractCode($response_str)
450  {
451  preg_match("|^HTTP/[\d\.x]+ (\d+)|", $response_str, $m);
452 
453  if (isset($m[1])) {
454  return (int) $m[1];
455  } else {
456  return false;
457  }
458  }
459 
466  public static function extractMessage($response_str)
467  {
468  preg_match("|^HTTP/[\d\.x]+ \d+ ([^\r\n]+)|", $response_str, $m);
469 
470  if (isset($m[1])) {
471  return $m[1];
472  } else {
473  return false;
474  }
475  }
476 
483  public static function extractVersion($response_str)
484  {
485  preg_match("|^HTTP/([\d\.x]+) \d+|", $response_str, $m);
486 
487  if (isset($m[1])) {
488  return $m[1];
489  } else {
490  return false;
491  }
492  }
493 
500  public static function extractHeaders($response_str)
501  {
502  $headers = array();
503 
504  // First, split body and headers. Headers are separated from the
505  // message at exactly the sequence "\r\n\r\n"
506  $parts = preg_split('|(?:\r\n){2}|m', $response_str, 2);
507  if (! $parts[0]) {
508  return $headers;
509  }
510 
511  // Split headers part to lines; "\r\n" is the only valid line separator.
512  $lines = explode("\r\n", $parts[0]);
513  unset($parts);
514  $last_header = null;
515 
516  foreach($lines as $index => $line) {
517  if ($index === 0 && preg_match('#^HTTP/\d+(?:\.\d+) [1-5]\d+#', $line)) {
518  // Status line; ignore
519  continue;
520  }
521 
522  if ($line == "") {
523  // Done processing headers
524  break;
525  }
526 
527  // Locate headers like 'Location: ...' and 'Location:...' (note the missing space)
528  if (preg_match("|^([a-zA-Z0-9\'`#$%&*+.^_\|\~!-]+):\s*(.*)|s", $line, $m)) {
529  unset($last_header);
530  $h_name = strtolower($m[1]);
531  $h_value = $m[2];
533 
534  if (isset($headers[$h_name])) {
535  if (! is_array($headers[$h_name])) {
536  $headers[$h_name] = array($headers[$h_name]);
537  }
538 
539  $headers[$h_name][] = ltrim($h_value);
540  $last_header = $h_name;
541  continue;
542  }
543 
544  $headers[$h_name] = ltrim($h_value);
545  $last_header = $h_name;
546  continue;
547  }
548 
549  // Identify header continuations
550  if (preg_match("|^[ \t](.+)$|s", $line, $m) && $last_header !== null) {
551  $h_value = trim($m[1]);
552  if (is_array($headers[$last_header])) {
553  end($headers[$last_header]);
554  $last_header_key = key($headers[$last_header]);
555 
556  $h_value = $headers[$last_header][$last_header_key] . $h_value;
558 
559  $headers[$last_header][$last_header_key] = $h_value;
560  continue;
561  }
562 
563  $h_value = $headers[$last_header] . $h_value;
565 
566  $headers[$last_header] = $h_value;
567  continue;
568  }
569 
570  // Anything else is an error condition
571  #require_once 'Zend/Http/Exception.php';
572  throw new Zend_Http_Exception('Invalid header line detected');
573  }
574 
575  return $headers;
576  }
577 
584  public static function extractBody($response_str)
585  {
586  $parts = preg_split('|(?:\r\n){2}|m', $response_str, 2);
587  if (isset($parts[1])) {
588  return $parts[1];
589  }
590  return '';
591  }
592 
599  public static function decodeChunkedBody($body)
600  {
601  $decBody = '';
602 
603  // If mbstring overloads substr and strlen functions, we have to
604  // override it's internal encoding
605  if (function_exists('mb_internal_encoding') &&
606  ((int) ini_get('mbstring.func_overload')) & 2) {
607 
608  $mbIntEnc = mb_internal_encoding();
609  mb_internal_encoding('ASCII');
610  }
611 
612  while (trim($body)) {
613  if (! preg_match("/^([\da-fA-F]+)[^\r\n]*\r\n/sm", $body, $m)) {
614  #require_once 'Zend/Http/Exception.php';
615  throw new Zend_Http_Exception("Error parsing body - doesn't seem to be a chunked message");
616  }
617 
618  $length = hexdec(trim($m[1]));
619  $cut = strlen($m[0]);
620  $decBody .= substr($body, $cut, $length);
621  $body = substr($body, $cut + $length + 2);
622  }
623 
624  if (isset($mbIntEnc)) {
625  mb_internal_encoding($mbIntEnc);
626  }
627 
628  return $decBody;
629  }
630 
639  public static function decodeGzip($body)
640  {
641  if (! function_exists('gzinflate')) {
642  #require_once 'Zend/Http/Exception.php';
643  throw new Zend_Http_Exception(
644  'zlib extension is required in order to decode "gzip" encoding'
645  );
646  }
647 
648  return gzinflate(substr($body, 10));
649  }
650 
659  public static function decodeDeflate($body)
660  {
661  if (! function_exists('gzuncompress')) {
662  #require_once 'Zend/Http/Exception.php';
663  throw new Zend_Http_Exception(
664  'zlib extension is required in order to decode "deflate" encoding'
665  );
666  }
667 
679  $zlibHeader = unpack('n', substr($body, 0, 2));
680  if ($zlibHeader[1] % 31 == 0 && ord($body[0]) == 0x78 && in_array(ord($body[1]), array(0x01, 0x5e, 0x9c, 0xda))) {
681  return gzuncompress($body);
682  } else {
683  return gzinflate($body);
684  }
685  }
686 
693  public static function fromString($response_str)
694  {
695  $code = self::extractCode($response_str);
696  $headers = self::extractHeaders($response_str);
697  $body = self::extractBody($response_str);
698  $version = self::extractVersion($response_str);
699  $message = self::extractMessage($response_str);
700 
702  }
703 }
static extractHeaders($response_str)
Definition: Response.php:500
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
static extractVersion($response_str)
Definition: Response.php:483
static fromString($response_str)
Definition: Response.php:693
$value
Definition: gender.phtml:16
getHeadersAsString($status_line=true, $br="\n")
Definition: Response.php:372
static decodeGzip($body)
Definition: Response.php:639
static decodeChunkedBody($body)
Definition: Response.php:599
asString($br="\r\n")
Definition: Response.php:402
getHeader($header)
Definition: Response.php:357
static extractBody($response_str)
Definition: Response.php:584
static extractMessage($response_str)
Definition: Response.php:466
__construct($code, array $headers, $body=null, $version='1.1', $message=null)
Definition: Response.php:156
$index
Definition: list.phtml:44
static decodeDeflate($body)
Definition: Response.php:659
static extractCode($response_str)
Definition: Response.php:449
static responseCodeAsText($code=null, $http11=true)
Definition: Response.php:429
if(!isset($_GET['name'])) $name
Definition: log.php:14