'lithium\net\http\Router', 'media' => 'lithium\net\http\Media', 'auth' => 'lithium\net\http\Auth' ]; /** * Auto configuration properties. * * @var array */ protected $_autoConfig = ['classes' => 'merge']; /** * Constructor. Adds config values to the public properties when a new object is created. * Config options also include default values for `Response::body()` when called from * `Response::render()`. * * @see lithium\net\http\Message::body() * @see lithium\net\http\Response::__construct() * @see lithium\net\http\Message::__construct() * @see lithium\net\Message::__construct() * @param array $config The available configuration options are the following. Further * options are inherited from the parent classes. * - `'buffer'` _integer_: Defaults to `null` * - `'decode'` _boolean_: Defaults to `null`. * - `'location'` _array|string|null_: Defaults to `null`. * - `'request'` _object_: Defaults to `null`. * @return void */ public function __construct(array $config = []) { $defaults = [ 'buffer' => 8192, 'location' => null, 'request' => null, 'decode' => false ]; parent::__construct($config + $defaults); } /** * Sets the Location header using `$config['location']` and `$config['request']` passed in * through the constructor if provided. * * @return void */ protected function _init() { parent::_init(); $router = $this->_classes['router']; if ($this->_config['location']) { $location = $router::match($this->_config['location'], $this->_config['request']); $this->headers('Location', $location); } } /** * Controls how or whether the client browser and web proxies should cache this response. * * @param mixed $expires This can be a Unix timestamp indicating when the page expires, or a * string indicating the relative time offset that a page should expire, i.e. `"+5 hours". * Finally, `$expires` can be set to `false` to completely disable browser or proxy * caching. * @return void */ public function cache($expires) { if ($expires === false) { $headers = [ 'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT', 'Cache-Control' => [ 'no-store, no-cache, must-revalidate', 'post-check=0, pre-check=0', 'max-age=0' ], 'Pragma' => 'no-cache' ]; } else { $expires = is_int($expires) ? $expires : strtotime($expires); $headers = [ 'Expires' => gmdate('D, d M Y H:i:s', $expires) . ' GMT', 'Cache-Control' => 'max-age=' . ($expires - time()), 'Pragma' => 'cache' ]; } $this->headers($headers); } /** * Sets/Gets the content type. If `'type'` is null, the method will attempt to determine the * type from the params, then from the environment setting * * @param string $type a full content type i.e. `'application/json'` or simple name `'json'` * @return string A simple content type name, i.e. `'html'`, `'xml'`, `'json'`, etc., depending * on the content type of the request. */ public function type($type = null) { if ($type === null && $this->_type === null) { $type = 'html'; } return parent::type($type); } /** * Render a response by writing headers and output. Output is echoed in * chunks because of an issue where `echo` time increases exponentially * on long message bodies. * * Reponses which have a `Location` header set are indicating a * redirect, will get their status code automatically adjusted to `302` * (Found/Moved Temporarily) in case the status code before was `200` * (OK). This is to allow easy redirects by setting just the `Location` * header and is assumed to be the original intent of the user. * * On responses with status codes `204` (No Content) and `302` (Found) * a message body - even if one is set - will never be send. These * status codes either don't have a message body as per their nature or * they are ignored and can thus be omitted for performance reasons. * * @return void */ public function render() { $code = null; if (isset($this->headers['location']) || isset($this->headers['Location'])) { if ($this->status['code'] === 200) { $this->status(302); } $code = $this->status['code']; } if ($cookies = $this->_cookies()) { $this->headers('Set-Cookie', $cookies); } $this->_writeHeaders($this->status() ?: $this->status(500)); $this->_writeHeaders($this->headers(), $code); if ($this->status['code'] === 302 || $this->status['code'] === 204) { return; } foreach ($this->body(null, $this->_config) as $chunk) { echo $chunk; } } /** * Casts the Response object to a string. This doesn't actually return a string, but does * a direct render and returns an empty string. * * @return string Just an empty string to satify requirements of this magic method. */ public function __toString() { $this->render(); return ''; } /** * Writes raw headers to output. * * @param string|array $headers Either a raw header string, or an array of header strings. Use * an array if a single header must be written multiple times with different values. * Otherwise, additional values for duplicate headers will overwrite previous values. * @param integer $code Optional. If present, forces a specific HTTP response code. Used * primarily in conjunction with the 'Location' header. * @return void */ protected function _writeHeaders($headers, $code = null) { foreach ((array) $headers as $header) { $code ? header($header, false, $code) : header($header, false); } } /* Deprecated / BC */ /** * Expands on `\net\http\Message::headers()` with some magic conversions for shorthand headers. * * @deprecated This method will be removed in a future version. Note that the parent `header()` * wil continue to exist. * @param string|array $key * @param mixed $value * @param boolean $replace * @return mixed */ public function headers($key = null, $value = null, $replace = true) { if ($key === 'download' || $key === 'Download') { $message = "Shorthand header `Download` with `` has been deprecated "; $message .= "because it's too magic. Please use `Content-Disposition` "; $message .= "with `attachment; filename=\"\"` instead."; trigger_error($message, E_USER_DEPRECATED); $key = 'Content-Disposition'; $value = 'attachment; filename="' . $value . '"'; } return parent::headers($key, $value, $replace); } } ?>