1<?php
2
3namespace Elastica\Transport;
4
5use Elastica\Connection;
6use Elastica\Exception\PartialShardFailureException;
7use Elastica\Exception\ResponseException;
8use Elastica\JSON;
9use Elastica\Request as ElasticaRequest;
10use Elastica\Response;
11use Elastica\Response as ElasticaResponse;
12use Elastica\Util;
13use Ivory\HttpAdapter\HttpAdapterInterface;
14use Ivory\HttpAdapter\Message\Request as HttpAdapterRequest;
15use Ivory\HttpAdapter\Message\Response as HttpAdapterResponse;
16use Ivory\HttpAdapter\Message\Stream\StringStream;
17
18\trigger_deprecation('ruflin/elastica', '7.1.1', 'The "%s" class is deprecated. It will be removed in 8.0.', HttpAdapter::class);
19
20/**
21 * @deprecated since version 7.1.1
22 */
23class HttpAdapter extends AbstractTransport
24{
25    /**
26     * @var HttpAdapterInterface
27     */
28    private $httpAdapter;
29
30    /**
31     * @var string
32     */
33    private $_scheme = 'http';
34
35    /**
36     * Construct transport.
37     */
38    public function __construct(?Connection $connection, HttpAdapterInterface $httpAdapter)
39    {
40        parent::__construct($connection);
41        $this->httpAdapter = $httpAdapter;
42    }
43
44    /**
45     * Makes calls to the elasticsearch server.
46     *
47     * All calls that are made to the server are done through this function
48     *
49     * @param array<string, mixed> $params Host, Port, ...
50     *
51     * @throws \Elastica\Exception\ConnectionException
52     * @throws ResponseException
53     * @throws \Elastica\Exception\Connection\HttpException
54     */
55    public function exec(ElasticaRequest $elasticaRequest, array $params): Response
56    {
57        $connection = $this->getConnection();
58
59        if ($timeout = $connection->getTimeout()) {
60            $this->httpAdapter->getConfiguration()->setTimeout($timeout);
61        }
62
63        $httpAdapterRequest = $this->_createHttpAdapterRequest($elasticaRequest, $connection);
64
65        $start = \microtime(true);
66        $httpAdapterResponse = $this->httpAdapter->sendRequest($httpAdapterRequest);
67        $end = \microtime(true);
68
69        $elasticaResponse = $this->_createElasticaResponse($httpAdapterResponse);
70        $elasticaResponse->setQueryTime($end - $start);
71
72        $elasticaResponse->setTransferInfo(
73            [
74                'request_header' => $httpAdapterRequest->getMethod(),
75                'http_code' => $httpAdapterResponse->getStatusCode(),
76            ]
77        );
78
79        if ($elasticaResponse->hasError()) {
80            throw new ResponseException($elasticaRequest, $elasticaResponse);
81        }
82
83        if ($elasticaResponse->hasFailedShards()) {
84            throw new PartialShardFailureException($elasticaRequest, $elasticaResponse);
85        }
86
87        return $elasticaResponse;
88    }
89
90    protected function _createElasticaResponse(HttpAdapterResponse $httpAdapterResponse): ElasticaResponse
91    {
92        return new ElasticaResponse((string) $httpAdapterResponse->getBody(), $httpAdapterResponse->getStatusCode());
93    }
94
95    protected function _createHttpAdapterRequest(ElasticaRequest $elasticaRequest, Connection $connection): HttpAdapterRequest
96    {
97        $data = $elasticaRequest->getData();
98        $body = null;
99        $method = $elasticaRequest->getMethod();
100        $headers = $connection->hasConfig('headers') ?: [];
101        if (!empty($data) || '0' === $data) {
102            if (ElasticaRequest::GET === $method) {
103                $method = ElasticaRequest::POST;
104            }
105
106            if ($this->hasParam('postWithRequestBody') && true == $this->getParam('postWithRequestBody')) {
107                $elasticaRequest->setMethod(ElasticaRequest::POST);
108                $method = ElasticaRequest::POST;
109            }
110
111            if (\is_array($data)) {
112                $body = JSON::stringify($data, \JSON_UNESCAPED_UNICODE);
113            } else {
114                $body = $data;
115            }
116        }
117
118        $url = $this->_getUri($elasticaRequest, $connection);
119        $streamBody = new StringStream($body);
120
121        return new HttpAdapterRequest($url, $method, HttpAdapterRequest::PROTOCOL_VERSION_1_1, $headers, $streamBody);
122    }
123
124    protected function _getUri(ElasticaRequest $request, Connection $connection): string
125    {
126        $url = $connection->hasConfig('url') ? $connection->getConfig('url') : '';
127
128        if (!empty($url)) {
129            $baseUri = $url;
130        } else {
131            $baseUri = $this->_scheme.'://'.$connection->getHost().':'.$connection->getPort().'/'.$connection->getPath();
132        }
133
134        $requestPath = $request->getPath();
135        if (!Util::isDateMathEscaped($requestPath)) {
136            $requestPath = Util::escapeDateMath($requestPath);
137        }
138
139        $baseUri .= $requestPath;
140
141        $query = $request->getQuery();
142
143        if (!empty($query)) {
144            $baseUri .= '?'.\http_build_query($query);
145        }
146
147        return $baseUri;
148    }
149}
150