Skip to content

Commit

Permalink
Merge pull request #29 from tyx/feature/18/leave_guzzle
Browse files Browse the repository at this point in the history
Replace guzzle3 with egeloen/ivory-http-adapter
  • Loading branch information
tyx committed Oct 29, 2015
2 parents a2a5e4e + 1d908c6 commit b6de2c0
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 114 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ default:
rest:
base_url: http://localhost:8888
store_response: true
adaptor_name: curl # Should be one of these adapters : https://github.com/egeloen/ivory-http-adapter/blob/master/doc/adapters.md#factory
suites:
default:
contexts:
- Rezzza\RestApiBehatExtension\RestApiContext
- Rezzza\RestApiBehatExtension\Json\JsonContext
```
Regarding the `adaptor_name` you choose, you will have to install the deps needed on your own.

## Usage
You can use directly the `JsonContext` or `RestApiContext` by loading them in your behat.yml or use the `RestApiBrowser` and `JsonInspector` by adding them in the construct of your own context.

Expand Down
1 change: 1 addition & 0 deletions behat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ default:
rest:
base_url: http://localhost:8888
store_response: true
adaptor_name: curl
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
"php": ">=5.3.2",
"behat/behat": "~3.0",
"atoum/atoum": "~1.0",
"guzzle/http": "~3.9",
"symfony/property-access": "~2.4",
"justinrainbow/json-schema": "~1.3"
"justinrainbow/json-schema": "~1.3",
"egeloen/http-adapter": "^0.8.0"
},
"require-dev": {
"silex/silex": "~1.0",
Expand Down
2 changes: 2 additions & 0 deletions src/Extension.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Extension implements ExtensionInterface
public function load(ContainerBuilder $container, array $config)
{
$container->setParameter('rezzza.json_api.rest.base_url', $config['rest']['base_url']);
$container->setParameter('rezzza.json_api.rest.adaptor_name', $config['rest']['adaptor_name']);
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/Resources'));
$loader->load('services.xml');

Expand All @@ -35,6 +36,7 @@ public function configure(ArrayNodeDefinition $builder)
->scalarNode('base_url')->end()
->booleanNode('store_response')
->defaultTrue()->end()
->scalarNode('adaptor_name')->end()
->end()
->end()
->end()
Expand Down
11 changes: 4 additions & 7 deletions src/Resources/services.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<container xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="rezzza.json_api.json.json_storage" class="Rezzza\RestApiBehatExtension\Json\JsonStorage" />
Expand All @@ -18,12 +18,9 @@
<tag name="context.argument_resolver" />
</service>

<service id="rezzza.json_api.rest.http_client" class="Guzzle\Http\Client" public="false">
<argument>%rezzza.json_api.rest.base_url%</argument>
</service>

<service id="rezzza.json_api.rest.rest_api_browser" class="Rezzza\RestApiBehatExtension\Rest\RestApiBrowser" public="false">
<argument type="service" id="rezzza.json_api.rest.http_client" />
<argument>%rezzza.json_api.rest.base_url%</argument>
<argument>%rezzza.json_api.rest.adaptor_name%</argument>
</service>

<service id="rezzza.json_api.rest.rest_api_browser.resolver" class="Rezzza\RestApiBehatExtension\Rest\RestApiBrowserResolver">
Expand Down
150 changes: 91 additions & 59 deletions src/Rest/RestApiBrowser.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,24 @@

namespace Rezzza\RestApiBehatExtension\Rest;

use Guzzle\Http\Exception\BadResponseException;
use Guzzle\Http\ClientInterface as HttpClient;
use Guzzle\Http\Message\Response;
use Ivory\HttpAdapter\HttpAdapterFactory;
use Ivory\HttpAdapter\HttpAdapterInterface as HttpClient;
use Ivory\HttpAdapter\HttpAdapterException;
use Ivory\HttpAdapter\Message\Request;
use Zend\Diactoros\Stream;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Behat\Gherkin\Node\PyStringNode;

class RestApiBrowser
{
/** @var HttpClient */
private $httpClient;

/** @var array|\Guzzle\Http\Message\RequestInterface */
/** @var RequestInterface */
private $request;

/** @var \Guzzle\Http\Message\Response|array */
/** @var ResponseInterface */
private $response;

/** @var array */
Expand All @@ -24,21 +28,50 @@ class RestApiBrowser
/** @var ResponseStorage */
private $responseStorage;

public function __construct(HttpClient $httpClient)
/**
* @param string $base_url
* @param string|null $adaptor_name
* @throws HttpAdapterException
*/
public function __construct($base_url, $adaptor_name, HttpClient $httpClient = null)
{
$this->httpClient = $httpClient;
if (!is_null($httpClient) && $httpClient instanceof HttpClient) {
$this->httpClient = $httpClient;
} else {
if (is_string($adaptor_name) && HttpAdapterFactory::capable($adaptor_name)) {
$this->httpClient = HttpAdapterFactory::create($adaptor_name);
} else {
$this->httpClient = HttpAdapterFactory::guess();
}
$this->httpClient->getConfiguration()->setBaseUri($base_url);
}
}

/**
* @param ResponseStorage $responseStorage
*/
public function enableResponseStorage(ResponseStorage $responseStorage)
{
$this->responseStorage = $responseStorage;
}


/**
* @return ResponseInterface
*/
public function getResponse()
{
return $this->response;
}

/**
* @param ResponseInterface $response
*/
public function setResponse(ResponseInterface $response)
{
$this->response = $response;
}

public function getRequest()
{
return $this->request;
Expand All @@ -49,83 +82,76 @@ public function getRequestHeaders()
return $this->requestHeaders;
}

/**
* @return HttpClient
*/
public function getHttpClient()
{
return $this->httpClient;
}

/**
* @param string $method
* @param string $url
* @param PyStringNode $body
* @param array $options
* @param string $body
*/
public function sendRequest($method, $url, $body = null, array $options = array())
public function sendRequest($method, $url, $body = null)
{
$this->createRequest($method, $url, $body, $options);

try {
$this->response = $this->httpClient->send($this->request);
} catch (BadResponseException $e) {
$this->response = $e->getResponse();
$this->send($method, $url, $body);
} catch (HttpAdapterException $e) {
if ($e->hasResponse()) {
$this->response = $e->getResponse();
}

if (null === $this->response) {
throw $e;
}
}

if (null !== $this->responseStorage) {
$this->responseStorage->writeRawContent($this->response->getBody(true));
$this->responseStorage->writeRawContent($this->response->getBody()->getContents());
}
}

/**
* @param string $name
* @param string $value
* @param string $method
* @param string $uri With or without host
* @param string|resource|array $body
*/
public function addRequestHeader($name, $value)
private function send($method, $uri, $body = null)
{
if (isset($this->requestHeaders[$name])) {
if (!is_array($this->requestHeaders[$name])) {
$this->requestHeaders[$name] = array($this->requestHeaders[$name]);
}
$this->requestHeaders[$name][] = $value;
} else {
$this->requestHeaders[$name] = $value;
if (!$this->hasHost($uri)) {
$uri = rtrim($this->httpClient->getConfiguration()->getBaseUri(), '/') . '/' . ltrim($uri, '/');
}
$stream = new Stream('php://memory', 'rw');
if ($body) {
$stream->write($body);
}
$this->request = new Request($uri, $method, $stream, $this->requestHeaders);
$this->response = $this->httpClient->send($uri, $method, $this->requestHeaders, $body);
// Reset headers used for the HTTP request
$this->requestHeaders = array();
}

/**
* @param string $name
* @param string $value
*/
public function setRequestHeader($name, $value)
{
$this->removeRequestHeader($name);
$this->addRequestHeader($name, $value);
}

/**
* @param Response $response
* @param string $uri
*
* @return bool
*/
public function setResponse(Response $response)
private function hasHost($uri)
{
$this->response = $response;
if (null !== $this->responseStorage) {
$this->responseStorage->writeRawContent($this->response->getBody(true));
}
return strpos($uri, '://') !== false;
}

/**
* @param string $method
* @param string $uri With or without host
* @param string|resource|array $body
* @param array $options
* @param string $name
* @param string $value
*/
private function createRequest($method, $uri, $body = null, array $options = array())
public function setRequestHeader($name, $value)
{
if (!$this->hasHost($uri)) {
$uri = rtrim($this->httpClient->getBaseUrl(), '/') . '/' . ltrim($uri, '/');
}

$this->request = $this->httpClient->createRequest($method, $uri, $this->requestHeaders, $body, $options);
// Reset headers used for the HTTP request
$this->requestHeaders = array();
$this->removeRequestHeader($name);
$this->addRequestHeader($name, $value);
}

private function removeRequestHeader($headerName)
Expand All @@ -136,12 +162,18 @@ private function removeRequestHeader($headerName)
}

/**
* @param string $uri
*
* @return bool
* @param string $name
* @param string $value
*/
private function hasHost($uri)
public function addRequestHeader($name, $value)
{
return strpos($uri, '://') !== false;
if (isset($this->requestHeaders[$name])) {
if (!is_array($this->requestHeaders[$name])) {
$this->requestHeaders[$name] = array($this->requestHeaders[$name]);
}
$this->requestHeaders[$name][] = $value;
} else {
$this->requestHeaders[$name] = $value;
}
}
}
Loading

0 comments on commit b6de2c0

Please sign in to comment.