Skip to content

Commit

Permalink
Start implementing request building.
Browse files Browse the repository at this point in the history
* Add highlevel tests for GET.
* Add tests for url building.
  • Loading branch information
markstory committed Dec 20, 2012
1 parent b869624 commit 55660bb
Show file tree
Hide file tree
Showing 2 changed files with 279 additions and 0 deletions.
155 changes: 155 additions & 0 deletions lib/Cake/Network/Http/Client.php
Expand Up @@ -13,9 +13,164 @@
*/ */
namespace Cake\Network\Http; namespace Cake\Network\Http;


use Cake\Network\Http\Request;
use Cake\Network\Http\Response;
use Cake\Utility\Hash;

/** /**
* The end user interface for doing HTTP requests. * The end user interface for doing HTTP requests.
* *
* ### Scoped clients
*
* ### Doing requests
*
* ### Using authentication
*
*/ */
class Client { class Client {

protected $_config = [];

protected $_adapter;

/**
* Create a new HTTP Client.
*
* ### Config options
*
*
* @param array $config Config options for scoped clients.
*/
public function __construct($config = []) {
$adapter = 'Cake\Network\Http\Adapter\Stream';
if (isset($config['adapter'])) {
$adapter = $config['adapter'];
unset($config['adapter']);
}
$this->_config = $config;

if (is_string($adapter)) {
$adapter = new $adapter();
}
$this->_adapter = $adapter;
}

/**
* Get or set additional config options.
*
* Setting config will use Hash::merge() for appending into
* the existing configuration.
*
* @param array|null $config Configuration options. null to get.
* @return this|array
*/
public function config($config = null) {
if ($config === null) {
return $this->_config;
}
$this->_config = Hash::merge($this->_config, $config);
return $this;
}

/**
* Do a GET request.
*
* @param string $url The url or path you want to request.
* @param array $data The query data you want to send.
* @param array $options Additional options for the request.
* @return Cake\Network\Http\Response
*/
public function get($url, $data = [], $options = []) {
$options = $this->_mergeOptions($options);
$request = $this->_createRequest(Request::METHOD_GET, $url, $data, $options);
return $this->_adapter->send($request, $options);
}

/**
* Do a POST request.
*
* @param string $url The url or path you want to request.
* @param array $data The post data you want to send.
* @param array $options Additional options for the request.
* @return Cake\Network\Http\Response
*/
public function post($url, $data = [], $options = []) {
}

/**
* Do a PUT request.
*
* @param string $url The url or path you want to request.
* @param array $data The request data you want to send.
* @param array $options Additional options for the request.
* @return Cake\Network\Http\Response
*/
public function put($url, $data = [], $options = []) {
}

/**
* Do a PATCH request.
*
* @param string $url The url or path you want to request.
* @param array $data The request data you want to send.
* @param array $options Additional options for the request.
* @return Cake\Network\Http\Response
*/
public function patch($url, $data = [], $options = []) {
}

/**
* Do a DELETE request.
*
* @param string $url The url or path you want to request.
* @param array $data The request data you want to send.
* @param array $options Additional options for the request.
* @return Cake\Network\Http\Response
*/
public function delete($url, $data = [], $options = []) {
}

protected function _mergeOptions($options)
{
return Hash::merge($this->_config, $options);
}

/**
* Generate a URL based on the scoped client options.
*
* @param string $url Either a full URL or just the path.
* @param array $options The config options stored with Client::config()
* @return string A complete url with scheme, port, host, path.
*/
public function buildUrl($url, $options = []) {
if (empty($options)) {
return $url;
}
$defaults = [
'host' => null,
'port' => null,
'scheme' => 'http',
];
$options = array_merge($defaults, (array)$options);
$defaultPorts = [
'http' => 80,
'https' => 443
];
$out = $options['scheme'] . '://' . $options['host'];
if ($options['port'] && $options['port'] != $defaultPorts[$options['scheme']]) {
$out .= ':' . $options['port'];
}
$out .= '/' . ltrim($url, '/');
return $out;
}

protected function _createRequest($method, $url, $data, $options) {
$url = $this->buildUrl($url, $options);
$request = new Request();
$request->method($method)
->url($url)
->content($data);
return $request;
}

} }
124 changes: 124 additions & 0 deletions lib/Cake/Test/TestCase/Network/Http/ClientTest.php
@@ -0,0 +1,124 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 3.0.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace Cake\Test\TestCase\Network\Http;

use Cake\Network\Http\Client;
use Cake\Network\Http\Request;
use Cake\Network\Http\Response;
use Cake\TestSuite\TestCase;

/**
* HTTP client test.
*/
class ClientTest extends TestCase {

/**
* Test storing config options and modifying them.
*
* @return void
*/
public function testConstructConfig() {
$config = [
'scheme' => 'http',
'host' => 'example.org',
];
$http = new Client($config);
$this->assertEquals($config, $http->config());

$result = $http->config([
'auth' => ['username' => 'mark', 'password' => 'secret']
]);
$this->assertSame($result, $http);

$result = $http->config();
$expected = [
'scheme' => 'http',
'host' => 'example.org',
'auth' => ['username' => 'mark', 'password' => 'secret']
];
$this->assertEquals($expected, $result);
}

public static function urlProvider() {
return [
[
// simple
'http://example.com/test.html',
'http://example.com/test.html',
null
],
[
// simple array opts
'http://example.com/test.html',
'http://example.com/test.html',
[]
],
[
'http://example.com/test.html',
'/test.html',
['host' => 'example.com']
],
[
'https://example.com/test.html',
'/test.html',
['host' => 'example.com', 'scheme' => 'https']
],
[
'http://example.com:8080/test.html',
'/test.html',
['host' => 'example.com', 'port' => '8080']
],
[
'http://example.com/test.html',
'/test.html',
['host' => 'example.com', 'port' => '80']
],
[
'https://example.com/test.html',
'/test.html',
['host' => 'example.com', 'scheme' => 'https', 'port' => '443']
],
];
}

/**
* @dataProvider urlProvider
*/
public function testBuildUrl($expected, $url, $opts) {
$http = new Client();

$result = $http->buildUrl($url, $opts);
$this->assertEquals($expected, $result);
}

public function testGet() {
$response = new Response();

$mock = $this->getMock('Cake\Network\Http\Adapter\Stream', ['send']);
$mock->expects($this->once())
->method('send')
->with($this->logicalAnd(
$this->isInstanceOf('Cake\Network\Http\Request')
))
->will($this->returnValue($response));

$http = new Client([
'host' => 'cakephp.org',
'adapter' => $mock
]);
$result = $http->get('/test.html');
$this->assertSame($result, $response);
}

}

0 comments on commit 55660bb

Please sign in to comment.