diff --git a/.gitattributes b/.gitattributes
index f8173ef..eecf37d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,8 +1,8 @@
-/tests export-ignore
-/.editorconfig export-ignore
-/.gitattributes export-ignore
-/.gitignore export-ignore
-/.scrutinizer.yml export-ignore
-/.travis.yml export-ignore
-/CONTRIBUTING.md export-ignore
-/phpunit.xml.dist export-ignore
+tests/ export-ignore
+.editorconfig export-ignore
+.gitattributes export-ignore
+.gitignore export-ignore
+.scrutinizer.yml export-ignore
+.travis.yml export-ignore
+CONTRIBUTING.md export-ignore
+phpunit.xml.dist export-ignore
diff --git a/.gitignore b/.gitignore
index bf5f069..e45d856 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-/build
-/vendor
-/composer.lock
-/phpunit.xml
+build/
+vendor/
+composer.lock
+phpunit.xml
diff --git a/.travis.yml b/.travis.yml
index 89e2828..79418fe 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -22,6 +22,9 @@ install:
- travis_retry composer self-update
- travis_retry composer update ${COMPOSER_FLAGS} --prefer-source --no-interaction
+before_script:
+ - vendor/bin/http_test_server > /dev/null 2>&1 &
+
script: vendor/bin/phpunit ${PHPUNIT_FLAGS}
after_script:
diff --git a/composer.json b/composer.json
index a6044fa..ccc969b 100644
--- a/composer.json
+++ b/composer.json
@@ -12,10 +12,13 @@
],
"require": {
"php": ">=5.4",
- "php-http/adapter-core": "dev-master"
+ "php-http/adapter-core": "0.1.*@dev",
+ "guzzlehttp/guzzle": "~5.1",
+ "guzzlehttp/ringphp": "^1.0.8@dev"
},
"require-dev": {
- "phpunit/phpunit": "~4.4"
+ "ext-curl": "*",
+ "php-http/adapter-integration-tests": "0.1.*@dev"
},
"provide": {
"php-http/adapter-implementation": "0.1"
@@ -25,6 +28,11 @@
"Http\\Adapter\\": "src/"
}
},
+ "autoload-dev": {
+ "psr-4": {
+ "Http\\Adapter\\Tests\\": "tests/"
+ }
+ },
"extra": {
"branch-alias": {
"dev-master": "0.1-dev"
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index fd71e68..fe68fd5 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -5,6 +5,9 @@
tests/
+
+
+
src/
diff --git a/src/Guzzle5HttpAdapter.php b/src/Guzzle5HttpAdapter.php
new file mode 100644
index 0000000..db6f969
--- /dev/null
+++ b/src/Guzzle5HttpAdapter.php
@@ -0,0 +1,171 @@
+
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Http\Adapter;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\ClientInterface;
+use GuzzleHttp\Event\CompleteEvent;
+use GuzzleHttp\Event\ErrorEvent;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Message\RequestInterface;
+use GuzzleHttp\Pool;
+use Http\Adapter\Message\InternalRequestInterface;
+use Http\Adapter\Normalizer\BodyNormalizer;
+
+/**
+ * @author GeLo
+ */
+class Guzzle5HttpAdapter extends CurlHttpAdapter
+{
+ /**
+ * @var ClientInterface
+ */
+ private $client;
+
+ /**
+ *
+ * @param ClientInterface|null $client
+ * @param ConfigurationInterface|null $configuration
+ */
+ public function __construct(ClientInterface $client = null, ConfigurationInterface $configuration = null)
+ {
+ parent::__construct($configuration);
+
+ $this->client = $client ?: new Client();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'guzzle5';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function sendInternalRequest(InternalRequestInterface $internalRequest)
+ {
+ try {
+ $response = $this->client->send($this->createRequest($internalRequest));
+ } catch (RequestException $e) {
+ throw HttpAdapterException::cannotFetchUri(
+ $e->getRequest()->getUrl(),
+ $this->getName(),
+ $e->getMessage()
+ );
+ }
+
+ return $this->getConfiguration()->getMessageFactory()->createResponse(
+ (integer) $response->getStatusCode(),
+ $response->getProtocolVersion(),
+ $response->getHeaders(),
+ BodyNormalizer::normalize(
+ function () use ($response) {
+ return $response->getBody()->detach();
+ },
+ $internalRequest->getMethod()
+ )
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function sendInternalRequests(array $internalRequests, $success, $error)
+ {
+ $requests = [];
+ foreach ($internalRequests as $internalRequest) {
+ $requests[] = $this->createRequest($internalRequest, $success, $error);
+ }
+
+ Pool::batch($this->client, $requests);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function createFile($file)
+ {
+ return fopen($file, 'r');
+ }
+
+ /**
+ * Creates a request.
+ *
+ * @param InternalRequestInterface $internalRequest
+ * @param callable|null $success
+ * @param callable|null $error
+ *
+ * @return RequestInterface
+ */
+ private function createRequest(InternalRequestInterface $internalRequest, callable $success = null, callable $error = null)
+ {
+ $request = $this->client->createRequest(
+ $internalRequest->getMethod(),
+ (string) $internalRequest->getUri(),
+ [
+ 'exceptions' => false,
+ 'allow_redirects' => false,
+ 'timeout' => $this->getConfiguration()->getTimeout(),
+ 'connect_timeout' => $this->getConfiguration()->getTimeout(),
+ 'version' => $internalRequest->getProtocolVersion(),
+ 'headers' => $this->prepareHeaders($internalRequest),
+ 'body' => $this->prepareContent($internalRequest),
+ ]
+ );
+
+ if (isset($success)) {
+ $messageFactory = $this->getConfiguration()->getMessageFactory();
+
+ $request->getEmitter()->on(
+ 'complete',
+ function (CompleteEvent $event) use ($success, $internalRequest, $messageFactory) {
+ $response = $messageFactory->createResponse(
+ (integer) $event->getResponse()->getStatusCode(),
+ $event->getResponse()->getProtocolVersion(),
+ $event->getResponse()->getHeaders(),
+ BodyNormalizer::normalize(
+ function () use ($event) {
+ return $event->getResponse()->getBody()->detach();
+ },
+ $internalRequest->getMethod()
+ )
+ );
+
+ $response = $response->withParameter('request', $internalRequest);
+ call_user_func($success, $response);
+ }
+ );
+ }
+
+ if (isset($error)) {
+ $httpAdapterName = $this->getName();
+
+ $request->getEmitter()->on(
+ 'error',
+ function (ErrorEvent $event) use ($error, $internalRequest, $httpAdapterName) {
+ $exception = HttpAdapterException::cannotFetchUri(
+ $event->getException()->getRequest()->getUrl(),
+ $httpAdapterName,
+ $event->getException()->getMessage()
+ );
+ $exception->setRequest($internalRequest);
+ call_user_func($error, $exception);
+ }
+ );
+ }
+
+ return $request;
+ }
+}
diff --git a/tests/Guzzle5CurlHttpAdapterTest.php b/tests/Guzzle5CurlHttpAdapterTest.php
new file mode 100644
index 0000000..d11f226
--- /dev/null
+++ b/tests/Guzzle5CurlHttpAdapterTest.php
@@ -0,0 +1,30 @@
+
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Http\Adapter\Tests;
+
+use GuzzleHttp\Ring\Client\CurlHandler;
+
+/**
+ * @requires PHP 5.5
+ *
+ * @author GeLo
+ */
+class Guzzle5CurlHttpAdapterTest extends Guzzle5HttpAdapterTest
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function createHandler()
+ {
+ return new CurlHandler();
+ }
+}
diff --git a/tests/Guzzle5HttpAdapterTest.php b/tests/Guzzle5HttpAdapterTest.php
new file mode 100644
index 0000000..b1bb62c
--- /dev/null
+++ b/tests/Guzzle5HttpAdapterTest.php
@@ -0,0 +1,41 @@
+
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Http\Adapter\Tests;
+
+use GuzzleHttp\Client;
+use Http\Adapter\Guzzle5HttpAdapter;
+
+/**
+ * @author GeLo
+ */
+abstract class Guzzle5HttpAdapterTest extends HttpAdapterTest
+{
+ public function testGetName()
+ {
+ $this->assertSame('guzzle5', $this->httpAdapter->getName());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function createHttpAdapter()
+ {
+ return new Guzzle5HttpAdapter(new Client(['handler' => $this->createHandler()]));
+ }
+
+ /**
+ * Returns a handler for the client
+ *
+ * @return object
+ */
+ abstract protected function createHandler();
+}
diff --git a/tests/Guzzle5MultiCurlHttpAdapterTest.php b/tests/Guzzle5MultiCurlHttpAdapterTest.php
new file mode 100644
index 0000000..2083cab
--- /dev/null
+++ b/tests/Guzzle5MultiCurlHttpAdapterTest.php
@@ -0,0 +1,28 @@
+
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Http\Adapter\Tests;
+
+use GuzzleHttp\Ring\Client\CurlMultiHandler;
+
+/**
+ * @author GeLo
+ */
+class Guzzle5MultiCurlHttpAdapterTest extends Guzzle5HttpAdapterTest
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function createHandler()
+ {
+ return new CurlMultiHandler();
+ }
+}
diff --git a/tests/Guzzle5StreamHttpAdapterTest.php b/tests/Guzzle5StreamHttpAdapterTest.php
new file mode 100644
index 0000000..21bc528
--- /dev/null
+++ b/tests/Guzzle5StreamHttpAdapterTest.php
@@ -0,0 +1,28 @@
+
+ *
+ * For the full copyright and license information, please read the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Http\Adapter\Tests;
+
+use GuzzleHttp\Ring\Client\StreamHandler;
+
+/**
+ * @author GeLo
+ */
+class Guzzle5StreamHttpAdapterTest extends Guzzle5HttpAdapterTest
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function createHandler()
+ {
+ return new StreamHandler();
+ }
+}