Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HttpClientTransport for Symfony HttpClient on Elastica #15

Merged
merged 3 commits into from Jan 16, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Expand Up @@ -16,6 +16,7 @@ Opinionated [Elastica](https://github.com/ruflin/Elastica) based framework to bo
- Analysis is separated from mappings;
- 100% compatibility with [ruflin/elastica](https://github.com/ruflin/Elastica);
- Designed for Elasticsearch 7+ (no types), compatible with both ES 6 and ES 7;
- Symfony HttpClient compatible transport;
- Extra commands to monitor, update mapping, reindex... Commonly implemented tasks.

## Demo
Expand Down Expand Up @@ -208,6 +209,19 @@ JoliCode\Elastically\Client:
elastically_bulk_size: 100
```

You can also use the Symfony HttpClient for all Elastica communications:

```yaml
JoliCode\Elastically\Transport\HttpClientTransport: ~
damienalexandre marked this conversation as resolved.
Show resolved Hide resolved

JoliCode\Elastically\Client:
arguments:
$config:
host: '%env(ELASTICSEARCH_HOST)%'
transport: '@JoliCode\Elastically\Transport\HttpClientTransport'
...
```

## To be done

- some "todo" in the code
Expand Down
117 changes: 117 additions & 0 deletions src/Transport/HttpClientTransport.php
@@ -0,0 +1,117 @@
<?php

namespace JoliCode\Elastically\Transport;

use Elastica\Connection;
use Elastica\Exception\Connection\HttpException;
use Elastica\Exception\PartialShardFailureException;
use Elastica\Exception\ResponseException;
use Elastica\Request;
use Elastica\Response;
use Elastica\Transport\AbstractTransport;
use Elastica\Util;
use Symfony\Component\HttpClient\Exception\ClientException;
use Symfony\Component\HttpClient\Exception\ServerException;
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
* Implement Symfony HttpClient as an Elastica Transport
*/
class HttpClientTransport extends AbstractTransport
{
private $client;

/**
* Elastica Connection does not have this option
*/
private $scheme;

public function __construct(HttpClientInterface $client, string $scheme = 'http', ?Connection $connection = null)
{
parent::__construct($connection);

$this->client = $client;
$this->scheme = $scheme;
}

public function exec(Request $request, array $params): Response
{
$connection = $this->getConnection();

$headers = $connection->hasConfig('headers') && \is_array($connection->getConfig('headers'))
? $connection->getConfig('headers')
: [];
$headers['Content-Type'] = $request->getContentType();

$options = [
'headers' => $headers,
'json' => $request->getData(),
];


if ($connection->getTimeout()) {
$options['timeout'] = $connection->getTimeout();
}

$proxy = $connection->getProxy();
if (!\is_null($proxy)) {
$options['proxy'] = $proxy;
}

try {
$response = $this->client->request($request->getMethod(), $this->_getUri($request, $connection), $options);
$elasticaResponse = new Response($response->getContent(), $response->getStatusCode());
} catch (ClientException $e) {
damienalexandre marked this conversation as resolved.
Show resolved Hide resolved
$elasticaResponse = new Response($response->getContent(false), $response->getStatusCode());
throw new ResponseException($request, $elasticaResponse);
} catch (ServerException $e) {
$elasticaResponse = new Response($response->getContent(false), $response->getStatusCode());
throw new ResponseException($request, $elasticaResponse);
} catch (HttpExceptionInterface $e) {
throw new HttpException($e->getCode(), $request);
}

if ($connection->hasConfig('bigintConversion')) {
$elasticaResponse->setJsonBigintConversion($connection->getConfig('bigintConversion'));
}

$elasticaResponse->setTransferInfo($response->getInfo());

if ($elasticaResponse->hasError()) {
throw new ResponseException($request, $elasticaResponse);
}

if ($elasticaResponse->hasFailedShards()) {
throw new PartialShardFailureException($request, $elasticaResponse);
}

return $elasticaResponse;
}

protected function _getUri(Request $request, Connection $connection): string
{
$url = $connection->hasConfig('url') ? $connection->getConfig('url') : '';

if (!empty($url)) {
$baseUri = $url;
} else {
$baseUri = $this->scheme.'://'.$connection->getHost().':'.$connection->getPort().'/'.$connection->getPath();
}

$requestPath = $request->getPath();
if (!Util::isDateMathEscaped($requestPath)) {
$requestPath = Util::escapeDateMath($requestPath);
}

$baseUri .= $requestPath;

$query = $request->getQuery();

if (!empty($query)) {
$baseUri .= '?'.\http_build_query($this->sanityzeQueryStringBool($query));
}

return $baseUri;
}
}