Skip to content

Commit

Permalink
Changing \action\Request to extend \net\http\Request, and overrid…
Browse files Browse the repository at this point in the history
…ing `to()` method to correct how URLs are generated. Adding documentation. Fixes #336.
  • Loading branch information
nateabele committed Apr 17, 2011
1 parent 8f1d9dc commit 621ef25
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 21 deletions.
25 changes: 22 additions & 3 deletions libraries/lithium/action/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* @see lithium\net\http\Route
* @see lithium\action\Request::__get()
*/
class Request extends \lithium\net\http\Message {
class Request extends \lithium\net\http\Request {

/**
* Current url of request.
Expand Down Expand Up @@ -501,9 +501,8 @@ public function detect($flag, $detector = null) {
* @param string $default Default URL to use if HTTP_REFERER cannot be read from headers.
* @param boolean $local If true, restrict referring URLs to local server.
* @return string Referring URL.
* @todo Rewrite me to remove constant dependencies.
*/
function referer($default = null, $local = false) {
public function referer($default = null, $local = false) {
if ($ref = $this->env('HTTP_REFERER')) {
if (!$local) {
return $ref;
Expand All @@ -515,6 +514,26 @@ function referer($default = null, $local = false) {
return ($default != null) ? $default : '/';
}

/**
* Overrides `lithium\net\http\Request::to()` to provide the correct options for generating
* URLs. For information about this method, see the parent implementation.
*
* @see lithium\net\http\Request::to()
* @param string $format The format to convert to.
* @param array $options Override options.
* @return mixed The return value type depends on `$format`.
*/
public function to($format, array $options = array()) {
$defaults = array(
'scheme' => $this->env('HTTPS') ? 'https' : 'http',
'host' => $this->env('HTTP_HOST'),
'path' => $this->_base . $this->url,
'query' => $this->query
);
$options += $defaults;
return parent::to($format, $options);
}

/**
* @todo Replace string directory names with configuration.
* @return void
Expand Down
8 changes: 6 additions & 2 deletions libraries/lithium/net/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

namespace lithium\net;

use ReflectionClass;
use ReflectionProperty;

/**
* Base message class for any URI based request/response.
* @see http://tools.ietf.org/html/rfc3986#section-1.1.1
Expand Down Expand Up @@ -117,8 +120,9 @@ public function to($format, array $options = array()) {
switch ($format) {
case 'array':
$array = array();
$r = new \ReflectionClass(get_class($this));
foreach ($r->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
$class = new ReflectionClass(get_class($this));

foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $prop) {
$array[$prop->getName()] = $prop->getValue($this);
}
return $array;
Expand Down
69 changes: 53 additions & 16 deletions libraries/lithium/net/http/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,31 +121,68 @@ public function queryString($params = array(), $format = "{:key}={:value}&") {

/**
* Converts the data in the record set to a different format, i.e. an array. Available
* options: array, url, context, or string.
* options: array, URL, stream context configuration, or string.
*
* @param string $format Format to convert to.
* @param array $options
* @return mixed
* @see lithium\net\Message::to()
* @param string $format Format to convert to. Should be either `'url'`, which returns a string
* representation of the URL that this request points to, or `'context'`, which
* returns an array usable with PHP's `stream_context_create()` function. For
* more available formats, see the parent method, `lithium\net\Message::to()`.
* @param array $options Allows overriding of specific portions of the URL, as follows. These
* options should only be specified if you intend to replace the values that are
* already in the `Request` object.
* - `'scheme'` _string_: The protocol scheme of the URL.
* - `'method'` _string_: If applicable, the HTTP method to use in the request.
* Mainly applies to the `'context'` format.
* - `'host'` _string_: The host name the request is pointing at.
* - `'port'` _string_: The host port, if any. If specified, should be prefixed
* with `':'`.
* - `'path'` _string_: The URL path.
* - `'query'` _mixed_: The query string of the URL as a string or array. If passed
* as a string, should be prefixed with `'?'`.
* - `'auth'` _string_: Authentication information. See the constructor for
* details.
* - `'content'` _string_: The body of the request.
* - `'headers'` _array_: The request headers.
* - `'version'` _string_: The HTTP version of the request, where applicable.
* @return mixed Varies; see the `$format` parameter for possible return values.
*/
public function to($format, array $options = array()) {
$defaults = array(
'method' => $this->method,
'scheme' => $this->scheme,
'host' => $this->host,
'port' => $this->port ? ":{$this->port}" : '',
'path' => $this->path,
'query' => $this->queryString(),
'auth' => $this->_config['auth'],
'content' => $this->body(),
'headers' => $this->headers(),
'version' => $this->version,
);
$options += $defaults;

if ($options['query'] && is_array($options['query'])) {
$options['query'] = $this->queryString($options['query']);
}

switch ($format) {
case 'url':
$query = $this->queryString();
$host = $this->host . ($this->port ? ":{$this->port}" : '');
return "{$this->scheme}://{$host}{$this->path}{$query}";
return String::insert("{:scheme}://{:host}{:port}{:path}{:query}", $options);
case 'context':
if ($this->_config['auth']) {
if ($options['auth']) {
$auth = base64_encode("{$this->username}:{$this->password}");
$this->headers('Authorization', "{$this->_config['auth']} {$auth}");
$this->headers('Authorization', "{$options['auth']} {$auth}");
}
$content = $this->body();
$this->headers('Content-Length', strlen($content));
$defaults = array(
'method' => $this->method,
'header' => $this->headers(), 'content' => $content,
'protocol_version' => $this->version, 'ignore_errors' => true
$this->headers('Content-Length', strlen($options['content']));
$base = array(
'content' => $options['content'],
'method' => $options['method'],
'header' => $options['headers'],
'protocol_version' => $options['version'],
'ignore_errors' => true
);
return array('http' => $options + $defaults);
return array('http' => array_diff_key($options, $defaults) + $base);
default:
return parent::to($format, $options);
}
Expand Down
15 changes: 15 additions & 0 deletions libraries/lithium/tests/cases/action/RequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,21 @@ public function testAcceptSingleContentType() {
$this->assertEqual(array('text/html'), $request->accepts(true));
$this->assertEqual('html', $request->accepts());
}

/**
* Tests that `action\Request` correctly inherits the functionality of the `to()` method
* inherited from `lithium\net\http\Request`.
*/
public function testConvertToUrl() {
$request = new Request(array(
'env' => array('HTTP_HOST' => 'foo.com', 'HTTPS' => 'on'),
'base' => '/the/base/path',
'url' => '/the/url',
'query' => array('some' => 'query', 'parameter' => 'values')
));
$expected = 'https://foo.com/the/base/path/the/url?some=query&parameter=values';
$this->assertEqual($expected, $request->to('url'));
}
}

?>

0 comments on commit 621ef25

Please sign in to comment.