Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Create a composer.json file in the project root:
{
"require": {
"sanchobbdo/api-auth-client-plugin": "~1.0.0",
"guzzle/guzzle": "~3.1"
"guzzle/guzzle": "~5.3"
}
}
```
Expand All @@ -33,12 +33,12 @@ Usage
require 'vendor/autoload.php';

// Use required Guzzle classess.
use Guzzle\Http\Client;
use GuzzleHttp\Client;

// Use the api_auth plugin.
use SanchoBBDO\Guzzle\Plugin\ApiAuth\ApiAuthPlugin;
use SanchoBBDO\GuzzleHttp\Plugin\ApiAuth\ApiAuthPlugin;

// Set up the Guzzle Client.
// Set up the GuzzleHttp Client.
$client = new Client('http://your-host.com');

// Set up the api_auth plugin. Include your access id and secret key.
Expand All @@ -48,7 +48,8 @@ $apiAuthPlugin = new ApiAuthPlugin(array(
));

// Subscribe the plugin to client's events.
$client->addSubscriber($apiAuthPlugin);
$emitter = $client->getEmmiter();
$emitter->attach($apiAuthPlugin);

// Enjoy!
```
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
}
],
"require-dev": {
"guzzle/guzzle": "~3.1",
"phpunit/phpunit": "3.7.*"
"guzzlehttp/guzzle": "~5.0",
"phpunit/phpunit": "4.*"
},
"autoload": {
"psr-0": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
* @filesource
*/

namespace SanchoBBDO\Guzzle\Plugin\ApiAuth;
namespace SanchoBBDO\GuzzleHttp\Plugin\ApiAuth;

use \GuzzleHttp\Collection;
use \GuzzleHttp\Event\BeforeEvent;
use \GuzzleHttp\Event\RequestEvents;
use \GuzzleHttp\Event\SubscriberInterface;
use \GuzzleHttp\Message\RequestInteface;
use \GuzzleHttp\Stream\StreamInterface;

use Guzzle\Common\Collection;
use Guzzle\Common\Event;
use Guzzle\Http\Message\RequestInteface;
use Guzzle\Http\Message\EntityEnclosingRequestInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* Api Auth signing plugin.
Expand All @@ -30,7 +32,7 @@
* @license MIT http://opensource.org/licenses/MIT
* @link http://
*/
class ApiAuthPlugin implements EventSubscriberInterface
class ApiAuthPlugin implements SubscriberInterface
{
/**
* @var Collection Configuration settings.
Expand All @@ -54,23 +56,23 @@ public function __construct($config)
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
public function getEvents()
{
return array(
'request.before_send' => array('onRequestBeforeSend', -1000)
'before' => array('onBefore', \GuzzleHttp\Event\RequestEvents::SIGN_REQUEST)
);
}

/**
* Request before-send handler.
* Request before handler.
*
* @param Event $event Event recieved.
* @param Event $event Event received.
*
* @return null
*/
public function onRequestBeforeSend(Event $event)
public function onBefore(BeforeEvent $event)
{
$request = $event['request'];
$request = $event->getRequest();

$this->setMD5HeaderOnRequest($request);
$this->setDateHeaderOnRequest($request);
Expand All @@ -95,16 +97,13 @@ protected function setMD5HeaderOnRequest($request)
/**
* Returns the request's body.
*
* Returns empty string if request is not a entity enclosing inteface.
*
* @param RequestInterface $request Request to get body from.
*
* @return string
*/
protected function getRequestBody($request)
{
return $request instanceof EntityEnclosingRequestInterface ?
(string) $request->getBody() : '';
return (string) $request->getBody();
}

/**
Expand Down Expand Up @@ -145,7 +144,7 @@ public function getCanonicalString($request)
$parts = array(
$request->getHeader('content-type'),
$request->getHeader('content-md5'),
$request->getPath().$request->getQuery(),
$request->getResource(),
$request->getHeader('date')
);

Expand Down
2 changes: 1 addition & 1 deletion src/http_date.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@
function http_date($timestamp = null)
{
$timestamp = empty($timestamp) ? time() : $timestamp;
return gmdate("D, d M Y H:i:s e", $timestamp);
return gmdate("D, d M Y H:i:s", $timestamp)." GMT";
}
}
61 changes: 43 additions & 18 deletions tests/SanchoBBDO/Tests/Guzzle/Plugin/ApiAuth/ApiAuthPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

namespace SanchoBBDO\Tests\Guzzle\Plugin\ApiAuth;

use Guzzle\Http\Message\RequestFactory;
use Guzzle\Common\Event;
use SanchoBBDO\Guzzle\Plugin\ApiAuth\ApiAuthPlugin;
use \GuzzleHttp\Client;
use \GuzzleHttp\Event\BeforeEvent;
use \GuzzleHttp\Message\Request;
use \GuzzleHttp\Stream\Stream;
use \GuzzleHttp\Transaction;
use \SanchoBBDO\GuzzleHttp\Plugin\ApiAuth\ApiAuthPlugin;

class ApiAuthPluginTest extends \PHPUnit_Framework_TestCase
{
const CANONICAL_STRING = 'text/plain,1B2M2Y8AsgTpgAmY7PhCfg==,/resource.xml?foo=bar&bar=foo,Mon, 23 Jan 1984 03:29:56 GMT';
const OTHER_CANONICAL_STRING = 'text/plain,1B2M2Y8AsgTpgAmY7PhCfg==,/resource.xml,Mon, 23 Jan 1984 03:29:56 GMT';
const ACCESS_ID = '1044';
const SECRET_KEY = 'ybqnM8UFztOwDfLOnsLlpUi+weSLvhiA5AigjUmRcWZ9dRSj1cnGWlnGKSAI\n+VT2VcdmQ3F61lfumx133MWcHw==';

Expand All @@ -24,14 +28,15 @@ public function setUp()

protected function mockBeforeSendFor($request)
{
$event = new Event(array('request' => $request));
$this->apiAuthPlugin->onRequestBeforeSend($event);
$t = new Transaction(new Client(), $request);
$event = new BeforeEvent($t);
$this->apiAuthPlugin->onBefore($event);
return $event;
}

protected function getRequest()
{
return RequestFactory::getInstance()->create(
return new Request(
'PUT',
'http://test.co/resource.xml?foo=bar&bar=foo',
array(
Expand All @@ -42,10 +47,23 @@ protected function getRequest()
);
}

protected function getOtherRequest()
{
return new Request(
'PUT',
'http://test.co/resource.xml',
array(
'Content-type' => "text/plain",
'Content-MD5' => "1B2M2Y8AsgTpgAmY7PhCfg==",
'Date' => "Mon, 23 Jan 1984 03:29:56 GMT"
)
);
}

public function testSubscribesToEvents()
{
$events = ApiAuthPlugin::getSubscribedEvents();
$this->assertArrayHasKey('request.before_send', $events);
$events = $this->apiAuthPlugin->getEvents();
$this->assertArrayHasKey('before', $events);
}

public function testAcceptsConfigurationData()
Expand All @@ -63,7 +81,7 @@ public function testAcceptsConfigurationData()

public function testShouldSetTheDateHeaderIfOneIsNotAlreadyPresent()
{
$request = RequestFactory::getInstance()->create(
$request = new Request(
'PUT',
'http://test.co/resource.xml?foo=bar&bar=foo',
array(
Expand All @@ -73,12 +91,12 @@ public function testShouldSetTheDateHeaderIfOneIsNotAlreadyPresent()
);

$event = $this->mockBeforeSendFor($request);
$this->assertNotEmpty($event['request']->getHeader('Date'));
$this->assertNotEmpty($event->getRequest()->getHeader('Date'));
}

public function testMD5HeaderNotAlreadyProvidedShouldCalculateForEmptyString()
{
$request = RequestFactory::getInstance()->create(
$request = new Request(
'PUT',
'http://test.co/resource.xml?foo=bar&bar=foo',
array(
Expand All @@ -89,27 +107,27 @@ public function testMD5HeaderNotAlreadyProvidedShouldCalculateForEmptyString()

$event = $this->mockBeforeSendFor($request);
$this->assertEquals(
(string) $event['request']->getHeader('Content-MD5'),
(string) $event->getRequest()->getHeader('Content-MD5'),
'1B2M2Y8AsgTpgAmY7PhCfg=='
);
}

public function testMD5HeaderShouldCalculateForRealContent()
{
$request = RequestFactory::getInstance()->create(
$request = new Request(
'PUT',
'http://test.co/resource.xml?foo=bar&bar=foo',
array(
'Content-type' => "text/plain",
'Date' => http_date()
),
"helo\nworld"
Stream::factory("hello\nworld")
);

$event = $this->mockBeforeSendFor($request);
$this->assertEquals(
(string) $event['request']->getHeader('Content-MD5'),
'MATnNnvfHYuh9MbanV26yg=='
(string) $event->getRequest()->getHeader('Content-MD5'),
'kZXQvrKoieG+Be1rsZVINw=='
);
}

Expand All @@ -119,7 +137,7 @@ public function testMD5HeaderShouldLeaveTheContentMD5AloneIfProvided()

$event = $this->mockBeforeSendFor($request);
$this->assertEquals(
(string) $event['request']->getHeader('Content-MD5'),
(string) $event->getRequest()->getHeader('Content-MD5'),
"1B2M2Y8AsgTpgAmY7PhCfg=="
);
}
Expand All @@ -131,6 +149,13 @@ public function testShouldGenerateTheProperCanonicalString()
$this->assertEquals(self::CANONICAL_STRING, $canonicalString);
}

public function testShouldGenerateTheProperCanonicalString2()
{
$request = $this->getOtherRequest();
$canonicalString = $this->apiAuthPlugin->getCanonicalString($request);
$this->assertEquals(self::OTHER_CANONICAL_STRING, $canonicalString);
}

public function testGetHMACSignatureGeneratesAValidSignature()
{
$request = $this->getRequest();
Expand All @@ -146,7 +171,7 @@ public function testShouldSignTheRequest()

$event = $this->mockBeforeSendFor($request);
$this->assertEquals(
(string) $event['request']->getHeader('Authorization'),
(string) $event->getRequest()->getHeader('Authorization'),
"APIAuth 1044:{$signature}"
);
}
Expand Down
2 changes: 0 additions & 2 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,5 @@
. "See http://getcomposer.org for help with installing composer\n");
}

require_once 'PHPUnit/TextUI/TestRunner.php';

// Include the composer autoloader
$autoloader = require dirname(__DIR__) . '/vendor/autoload.php';