From 0cd8a7a2769719f0d54b48ecbe0586ffdbd7aaa5 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Fri, 28 Apr 2017 09:46:08 -0400 Subject: [PATCH] Add WireHttp::getResponseHeaderValues() per processwire/processwire-issues#253 --- wire/core/WireHttp.php | 57 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/wire/core/WireHttp.php b/wire/core/WireHttp.php index dd6855a9..cf96cc41 100644 --- a/wire/core/WireHttp.php +++ b/wire/core/WireHttp.php @@ -191,6 +191,14 @@ class WireHttp extends Wire { */ protected $responseHeaders = array(); + /** + * Last response headers parsed into key => value properties, where value is always array + * + * Note that keys are always lowercase + * + */ + protected $responseHeaderArrays = array(); + /** * Error messages * @@ -821,10 +829,16 @@ class WireHttp extends Wire { * Get the last HTTP response headers (associative array) * * All headers are translated to `[key => value]` properties in the array. - * The keys are always lowercase. + * The keys are always lowercase and the values are always strings. If you + * need multi-value headers, use the `WireHttp::getResponseHeaderValues()` method + * instead, which returns multi-value headers as arrays. + * + * This method always returns an associative array of strings, unless you specify the + * `$key` option in which case it will return a string, or NULL if the header is not present. * * @param string $key Optional header name you want to get (if you only need one) * @return array|string|null + * @see WireHttp::getResponseHeaderValues() * */ public function getResponseHeaders($key = '') { @@ -834,6 +848,37 @@ class WireHttp extends Wire { } return $this->responseHeaders; } + + /** + * Get last HTTP response headers with multi-value headers as arrays + * + * Use this method when you want to retrieve headers that can potentially contain multiple-values. + * Note that any code that iterates these values should be able to handle them being either a string or + * an array. + * + * This method always returns an associative array of strings and arrays, unless you specify the + * `$key` option in which case it can return an array, string, or NULL if the header is not present. + * + * @param string $key Optional header name you want to get (if you only need a specific header) + * @param bool $forceArrays If even single-value headers should be arrays, specify true (default=false). + * @return array|string|null + * + */ + public function getResponseHeaderValues($key = '', $forceArrays = false) { + if(!empty($key)) { + $key = strtolower($key); + $value = isset($this->responseHeaderArrays[$key]) ? $this->responseHeaderArrays[$key] : null; + if(!$value !== null && count($value) === 1 && !$forceArrays) $value = reset($value); + } else if($forceArrays) { + $value = $this->responseHeaderArrays; + } else { + $value = $this->responseHeaders; + foreach($this->responseHeaderArrays as $k => $v) { + if(count($v) > 1) $value[$k] = $v; + } + } + return $value; + } /** * Set the response header @@ -847,6 +892,7 @@ class WireHttp extends Wire { if(!empty($responseHeader[0])) { list($http, $httpCode, $httpText) = explode(' ', trim($responseHeader[0]), 3); + if($http) {} // ignore $httpCode = (int) $httpCode; $httpText = preg_replace('/[^-_.;() a-zA-Z0-9]/', ' ', $httpText); } else { @@ -861,6 +907,8 @@ class WireHttp extends Wire { // parsed version $this->responseHeaders = array(); + $this->responseHeaderArrays = array(); + foreach($responseHeader as $header) { $pos = strpos($header, ':'); if($pos !== false) { @@ -870,7 +918,12 @@ class WireHttp extends Wire { $key = $header; $value = ''; } - if(!isset($this->responseHeaders[$key])) $this->responseHeaders[$key] = $value; + if(!isset($this->responseHeaders[$key])) { + $this->responseHeaders[$key] = $value; + $this->responseHeaderArrays[$key] = array($value); + } else { + $this->responseHeaderArrays[$key][] = $value; + } } /*