From 7b8697f3c8356d7d780549d4f5b3402aaa3fc06f Mon Sep 17 00:00:00 2001 From: Lucas Perez Date: Wed, 25 Jan 2017 17:11:35 -0300 Subject: [PATCH 1/3] Ensure that the date timestamp has 'GMT' instead of UTC --- src/http_date.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http_date.php b/src/http_date.php index 30afe5a..f142c55 100644 --- a/src/http_date.php +++ b/src/http_date.php @@ -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"; } } From 2ed80ccbbbce6a1ef1557b24e29abe2afd26726a Mon Sep 17 00:00:00 2001 From: Lucas Perez Date: Wed, 25 Jan 2017 19:59:14 -0300 Subject: [PATCH 2/3] Update for Guzzle 5.x --- composer.json | 4 +- .../Plugin/ApiAuth/ApiAuthPlugin.php | 35 ++++++----- src/http_date.php | 2 +- .../Plugin/ApiAuth/ApiAuthPluginTest.php | 61 +++++++++++++------ tests/bootstrap.php | 2 - 5 files changed, 63 insertions(+), 41 deletions(-) rename src/SanchoBBDO/{Guzzle => GuzzleHttp}/Plugin/ApiAuth/ApiAuthPlugin.php (82%) diff --git a/composer.json b/composer.json index 3cb91ff..ffa9026 100644 --- a/composer.json +++ b/composer.json @@ -12,8 +12,8 @@ } ], "require-dev": { - "guzzle/guzzle": "~3.1", - "phpunit/phpunit": "3.7.*" + "guzzlehttp/guzzle": "~5.0", + "phpunit/phpunit": "4.*" }, "autoload": { "psr-0": { diff --git a/src/SanchoBBDO/Guzzle/Plugin/ApiAuth/ApiAuthPlugin.php b/src/SanchoBBDO/GuzzleHttp/Plugin/ApiAuth/ApiAuthPlugin.php similarity index 82% rename from src/SanchoBBDO/Guzzle/Plugin/ApiAuth/ApiAuthPlugin.php rename to src/SanchoBBDO/GuzzleHttp/Plugin/ApiAuth/ApiAuthPlugin.php index 898bd66..2ff4b15 100644 --- a/src/SanchoBBDO/Guzzle/Plugin/ApiAuth/ApiAuthPlugin.php +++ b/src/SanchoBBDO/GuzzleHttp/Plugin/ApiAuth/ApiAuthPlugin.php @@ -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. @@ -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. @@ -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); @@ -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(); } /** @@ -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') ); diff --git a/src/http_date.php b/src/http_date.php index f142c55..64fe563 100644 --- a/src/http_date.php +++ b/src/http_date.php @@ -23,6 +23,6 @@ function http_date($timestamp = null) { $timestamp = empty($timestamp) ? time() : $timestamp; - return gmdate("D, d M Y H:i:s", $timestamp)."GMT"; + return gmdate("D, d M Y H:i:s", $timestamp)." GMT"; } } diff --git a/tests/SanchoBBDO/Tests/Guzzle/Plugin/ApiAuth/ApiAuthPluginTest.php b/tests/SanchoBBDO/Tests/Guzzle/Plugin/ApiAuth/ApiAuthPluginTest.php index e2adbb8..5c4fcf3 100644 --- a/tests/SanchoBBDO/Tests/Guzzle/Plugin/ApiAuth/ApiAuthPluginTest.php +++ b/tests/SanchoBBDO/Tests/Guzzle/Plugin/ApiAuth/ApiAuthPluginTest.php @@ -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=='; @@ -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( @@ -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() @@ -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( @@ -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( @@ -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==' ); } @@ -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==" ); } @@ -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(); @@ -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}" ); } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 1c4bc62..8dbfe42 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -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'; From 487aafcbeac6c2c388e24740d9fbb390a3f68484 Mon Sep 17 00:00:00 2001 From: Lucas Perez Date: Thu, 26 Jan 2017 11:55:54 -0300 Subject: [PATCH 3/3] Update readme --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5b6b512..cad40d5 100644 --- a/README.md +++ b/README.md @@ -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" } } ``` @@ -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. @@ -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! ```