Initial
This commit is contained in:
239
system/HTTP/MessageTrait.php
Normal file
239
system/HTTP/MessageTrait.php
Normal file
@@ -0,0 +1,239 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\HTTP;
|
||||
|
||||
use CodeIgniter\HTTP\Exceptions\HTTPException;
|
||||
|
||||
/**
|
||||
* Message Trait
|
||||
* Additional methods to make a PSR-7 Message class
|
||||
* compliant with the framework's own MessageInterface.
|
||||
*
|
||||
* @see https://github.com/php-fig/http-message/blob/master/src/MessageInterface.php
|
||||
*/
|
||||
trait MessageTrait
|
||||
{
|
||||
/**
|
||||
* List of all HTTP request headers.
|
||||
*
|
||||
* @var array<string, Header>
|
||||
*/
|
||||
protected $headers = [];
|
||||
|
||||
/**
|
||||
* Holds a map of lower-case header names
|
||||
* and their normal-case key as it is in $headers.
|
||||
* Used for case-insensitive header access.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $headerMap = [];
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Body
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets the body of the current message.
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setBody($data): self
|
||||
{
|
||||
$this->body = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends data to the body of the current message.
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function appendBody($data): self
|
||||
{
|
||||
$this->body .= (string) $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Headers
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Populates the $headers array with any headers the getServer knows about.
|
||||
*/
|
||||
public function populateHeaders(): void
|
||||
{
|
||||
$contentType = $_SERVER['CONTENT_TYPE'] ?? getenv('CONTENT_TYPE');
|
||||
if (! empty($contentType)) {
|
||||
$this->setHeader('Content-Type', $contentType);
|
||||
}
|
||||
unset($contentType);
|
||||
|
||||
foreach (array_keys($_SERVER) as $key) {
|
||||
if (sscanf($key, 'HTTP_%s', $header) === 1) {
|
||||
// take SOME_HEADER and turn it into Some-Header
|
||||
$header = str_replace('_', ' ', strtolower($header));
|
||||
$header = str_replace(' ', '-', ucwords($header));
|
||||
|
||||
$this->setHeader($header, $_SERVER[$key]);
|
||||
|
||||
// Add us to the header map so we can find them case-insensitively
|
||||
$this->headerMap[strtolower($header)] = $header;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all Headers.
|
||||
*
|
||||
* @return array<string, Header> An array of the Header objects
|
||||
*/
|
||||
public function headers(): array
|
||||
{
|
||||
// If no headers are defined, but the user is
|
||||
// requesting it, then it's likely they want
|
||||
// it to be populated so do that...
|
||||
if (empty($this->headers)) {
|
||||
$this->populateHeaders();
|
||||
}
|
||||
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single Header object. If multiple headers with the same
|
||||
* name exist, then will return an array of header objects.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return array|Header|null
|
||||
*/
|
||||
public function header($name)
|
||||
{
|
||||
$origName = $this->getHeaderName($name);
|
||||
|
||||
return $this->headers[$origName] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a header and it's value.
|
||||
*
|
||||
* @param array|string|null $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeader(string $name, $value): self
|
||||
{
|
||||
$origName = $this->getHeaderName($name);
|
||||
|
||||
if (isset($this->headers[$origName]) && is_array($this->headers[$origName]->getValue())) {
|
||||
if (! is_array($value)) {
|
||||
$value = [$value];
|
||||
}
|
||||
|
||||
foreach ($value as $v) {
|
||||
$this->appendHeader($origName, $v);
|
||||
}
|
||||
} else {
|
||||
$this->headers[$origName] = new Header($origName, $value);
|
||||
$this->headerMap[strtolower($origName)] = $origName;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a header from the list of headers we track.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeHeader(string $name): self
|
||||
{
|
||||
$origName = $this->getHeaderName($name);
|
||||
unset($this->headers[$origName], $this->headerMap[strtolower($name)]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an additional header value to any headers that accept
|
||||
* multiple values (i.e. are an array or implement ArrayAccess)
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function appendHeader(string $name, ?string $value): self
|
||||
{
|
||||
$origName = $this->getHeaderName($name);
|
||||
|
||||
array_key_exists($origName, $this->headers)
|
||||
? $this->headers[$origName]->appendValue($value)
|
||||
: $this->setHeader($name, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an additional header value to any headers that accept
|
||||
* multiple values (i.e. are an array or implement ArrayAccess)
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function prependHeader(string $name, string $value): self
|
||||
{
|
||||
$origName = $this->getHeaderName($name);
|
||||
|
||||
$this->headers[$origName]->prependValue($value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a header name in any case, and returns the
|
||||
* normal-case version of the header.
|
||||
*/
|
||||
protected function getHeaderName(string $name): string
|
||||
{
|
||||
return $this->headerMap[strtolower($name)] ?? $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the HTTP protocol version.
|
||||
*
|
||||
* @throws HTTPException For invalid protocols
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setProtocolVersion(string $version): self
|
||||
{
|
||||
if (! is_numeric($version)) {
|
||||
$version = substr($version, strpos($version, '/') + 1);
|
||||
}
|
||||
|
||||
// Make sure that version is in the correct format
|
||||
$version = number_format((float) $version, 1);
|
||||
|
||||
if (! in_array($version, $this->validProtocolVersions, true)) {
|
||||
throw HTTPException::forInvalidHTTPProtocol(implode(', ', $this->validProtocolVersions));
|
||||
}
|
||||
|
||||
$this->protocolVersion = $version;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user