nodespark/des-connector

Support for Elasticsearch ClientBuilder->setHandler()

Closed this issue · 1 comments

jover commented

Currently there's no support for adding handlers to the Elasticsearch ClientBuilder.

The Drupal module elasticsearch_connector has a hook hook_elasticsearch_connector_load_library_options_alter which allows developers to define extra functionality related to the connection to an Elasticsearch instance.

This is necessary to for example sign requests in case using the AWS Elasticsearch Service.
Example:

function hook_elasticsearch_connector_load_library_options_alter(array &$options) {
  $psr7Handler = Aws\default_http_handler();
  $signer = new SignatureV4('es', 'eu-west-1');
  $credentialProvider = CredentialProvider::defaultProvider();

  // Construct the handler that will be used by Elasticsearch-PHP.
  $options['handler'] = function (array $request) use (
    $psr7Handler,
    $signer,
    $credentialProvider
  ) {
    // Amazon ES listens on standard ports (443 for HTTPS, 80 for HTTP).
    $request['headers']['host'][0] = parse_url($request['headers']['host'][0], PHP_URL_HOST);

    // Create a PSR-7 request from the array passed to the handler.
    $psr7Request = new Request(
      $request['http_method'],
      (new Uri($request['uri']))
        ->withScheme($request['scheme'])
        ->withHost($request['headers']['host'][0]),
      $request['headers'],
      $request['body']
    );

    // Sign the PSR-7 request with credentials from the environment.
    try {
      $signedRequest = $signer->signRequest(
        $psr7Request,
        call_user_func($credentialProvider)->wait()
      );

      // Send the signed request to Amazon ES.
      /** @var \Psr\Http\Message\ResponseInterface $response */
      $response = $psr7Handler($signedRequest)->wait();

      // Convert the PSR-7 response to a RingPHP response.
      return new CompletedFutureArray([
        'status' => $response->getStatusCode(),
        'headers' => $response->getHeaders(),
        'body' => $response->getBody()->detach(),
        'transfer_stats' => ['total_time' => 0],
        'effective_url' => (string) $psr7Request->getUri(),
      ]);
    }
    catch (RejectionException $e) {
      /** @var GuzzleHttp\Psr7\Response $response */
      $response = $e->getReason()['response'];
      echo (string) $response->getBody();
      /** @var GuzzleHttp\Psr7\Request $request */
      $request = $e->getReason()['request'];

      \Drupal::logger('AWS')->error('The request to Amazon could not be signed successfully. Request URI: ' . $request->getUri());
    }
  };
}

DES-connector should pass this handler function to the function Elasticsearch ClientBuilder->setHandler().

@jover, thank you for the patch.