CurlAdapter   A
last analyzed

Complexity

Total Complexity 31

Size/Duplication

Total Lines 338
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 31
eloc 102
dl 0
loc 338
ccs 132
cts 132
cp 1
rs 9.92
c 0
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A getAdaptee() 0 3 1
A __construct() 0 3 1
A setAdaptee() 0 4 1
A isPostOrPutRequest() 0 4 2
A getCurlClient() 0 6 1
A createBaseHeaderList() 0 8 1
A curlExec() 0 7 3
A initParams() 0 17 3
A httpRequest() 0 19 2
A setBaseOpt() 0 9 1
A createCookieHeaderList() 0 11 3
A setHedaers() 0 13 2
A triggerAuthentication() 0 11 2
A setDefaultOpt() 0 10 1
A request() 0 19 1
A triggerEnablePostParams() 0 6 2
A createCustomHeaderList() 0 7 2
A triggerDisableSSLCertificateValidation() 0 10 2
1
<?php
2
/**
3
 * @category    Brownie/HttpClient
4
 * @author      Brownie <[email protected]>
5
 * @license     https://opensource.org/licenses/MIT
6
 */
7
8
namespace Brownie\HttpClient\Client;
9
10
use Brownie\HttpClient\Cookie\CookieList;
11
use Brownie\HttpClient\Header\HeaderList;
12
use Brownie\HttpClient\RawResponse;
13
use Brownie\HttpClient\Request;
14
use Brownie\HttpClient\Response;
15
use Brownie\HttpClient\Client;
16
use Brownie\HttpClient\Exception\ClientException;
17
18
/**
19
 * API(Adapter) for using CURL functions in HTTP requests.
20
 */
21
class CurlAdapter implements Client
22
{
23
24
    /**
25
     * API CURL functions.
26
     *
27
     * @var CurlAdaptee
28
     */
29
    private $adaptee;
30
31
    /**
32
     * Sets incoming data.
33
     *
34
     * @param CurlAdaptee       $adaptee        API CURL functions.
35
     */
36 9
    public function __construct(CurlAdaptee $adaptee)
37
    {
38 9
        $this->setAdaptee($adaptee);
39 9
    }
40
41
    /**
42
     * Sets API CURL functions wrapper.
43
     * Returns the current object.
44
     *
45
     * @param CurlAdaptee $adaptee
46
     *
47
     * @return self
48
     */
49 9
    private function setAdaptee(CurlAdaptee $adaptee)
50
    {
51 9
        $this->adaptee = $adaptee;
52 9
        return $this;
53
    }
54
55
    /**
56
     * Returns API CURL functions wrapper.
57
     *
58
     * @return CurlAdaptee
59
     */
60 9
    private function getAdaptee()
61
    {
62 9
        return $this->adaptee;
63
    }
64
65
    /**
66
     * Performs a network request.
67
     * Returns the response.
68
     *
69
     * @param Request       $request    HTTP request params.
70
     *
71
     * @throws ClientException
72
     *
73
     * @return Response
74
     */
75 9
    public function httpRequest(Request $request)
76
    {
77 9
        $rawResponse = $this->request($request);
78
        /**
79
         * Gets the HTTP headers and the body separately.
80
         */
81 8
        $body = substr($rawResponse->getResponseBody(), $rawResponse->getHeaderSize());
82 8
        if (empty($body)) {
83 1
            $body = '';
84 1
        }
85 8
        $httpHeadersString = substr($rawResponse->getResponseBody(), 0, $rawResponse->getHeaderSize());
86
87 8
        $response = new Response();
88
        return $response
89 8
            ->setBody($body)
90 8
            ->setHttpCode($rawResponse->getHttpCode())
91 8
            ->setRuntime($rawResponse->getRuntime())
92 8
            ->setHttpHeaderList(new HeaderList($httpHeadersString))
93 8
            ->setHttpCookieList(new CookieList($httpHeadersString));
94
    }
95
96
    /**
97
     * Executes a network resource request.
98
     *
99
     * @param Request       $request    HTTP request params.
100
     *
101
     * @return RawResponse
102
     */
103 9
    private function request(Request $request)
104
    {
105 9
        $this->initParams($request);
106
107 9
        $curl = $this->getCurlClient($request);
108 9
        $responseBody = $this->curlExec($curl);
109
110 8
        $runtime = $this->getAdaptee()->getinfo($curl, CURLINFO_TOTAL_TIME);
111 8
        $httpCode = $this->getAdaptee()->getinfo($curl, CURLINFO_HTTP_CODE);
112 8
        $headerSize = $this->getAdaptee()->getinfo($curl, CURLINFO_HEADER_SIZE);
113
114 8
        $this->getAdaptee()->close($curl);
115
116 8
        return new RawResponse(
117
            array(
118 8
                'runtime' => $runtime,
119 8
                'httpCode' => $httpCode,
120 8
                'headerSize' => $headerSize,
121
                'responseBody' => $responseBody
122 8
            )
123 8
        );
124
    }
125
126
    /**
127
     * Perform a request session.
128
     * Returns the body of the response
129
     *
130
     * @param resource      $curl       Curl client.
131
     *
132
     * @return string
133
     *
134
     * @throws ClientException
135
     */
136 9
    private function curlExec($curl)
137
    {
138 9
        $responseBody = $this->getAdaptee()->exec($curl);
139 9
        if ((0 != $this->getAdaptee()->errno($curl)) || !is_string($responseBody)) {
140 1
            throw new ClientException($this->getAdaptee()->error($curl));
141
        }
142 8
        return $responseBody;
143
    }
144
145
    /**
146
     * Creates and returns a CURL resource.
147
     *
148
     * @param Request       $request        HTTP request params.
149
     *
150
     * @return resource
151
     */
152 9
    private function getCurlClient(Request $request)
153
    {
154 9
        $curl = $this->getAdaptee()->init($request->getUrl());
155 9
        $this->setBaseOpt($curl, $request);
156 9
        $this->setHedaers($curl, $request);
157 9
        return $curl;
158
    }
159
160
    /**
161
     * Sets the basic options.
162
     *
163
     * @param resource  $curl       CURL resource.
164
     * @param Request   $request    HTTP request params.
165
     */
166 9
    private function setBaseOpt($curl, Request $request)
167
    {
168 9
        $this->setDefaultOpt($curl, $request);
169 9
        $this->triggerEnablePostParams($curl, $request);
170 9
        $this->triggerDisableSSLCertificateValidation($curl, $request);
171 9
        $this->triggerAuthentication($curl, $request);
172 9
        $this
173 9
            ->getAdaptee()
174 9
            ->setopt($curl, CURLOPT_POSTFIELDS, $request->getBody());
175 9
    }
176
177
    /**
178
     * Sets the default values.
179
     *
180
     * @param resource  $curl       CURL resource.
181
     * @param Request   $request    HTTP request params.
182
     */
183 9
    private function setDefaultOpt($curl, Request $request)
184
    {
185 9
        $this
186 9
            ->getAdaptee()
187 9
            ->setopt($curl, CURLOPT_CUSTOMREQUEST, $request->getMethod())
188 9
            ->setopt($curl, CURLOPT_TIMEOUT, $request->getTimeOut())
189 9
            ->setopt($curl, CURLOPT_NOPROGRESS, true)
190 9
            ->setopt($curl, CURLOPT_RETURNTRANSFER, true)
191 9
            ->setopt($curl, CURLOPT_URL, $request->getUrl())
192 9
            ->setopt($curl, CURLOPT_HEADER, true);
193 9
    }
194
195
    /**
196
     * Configures POST data.
197
     *
198
     * @param resource  $curl       CURL resource.
199
     * @param Request   $request    HTTP request params.
200
     */
201 9
    private function triggerEnablePostParams($curl, Request $request)
202
    {
203 9
        if ($this->isPostOrPutRequest($request)) {
204 1
            $this
205 1
                ->getAdaptee()
206 1
                ->setopt($curl, CURLOPT_POST, true);
207 1
        }
208 9
    }
209
210
    /**
211
     * Returns the POST or PUT request flag.
212
     *
213
     * @param Request   $request    HTTP request params.
214
     *
215
     * @return bool
216
     */
217 9
    private function isPostOrPutRequest(Request $request)
218
    {
219 9
        return (Request::HTTP_METHOD_POST == $request->getMethod()) ||
220 9
            (Request::HTTP_METHOD_PUT == $request->getMethod());
221
    }
222
223
    /**
224
     * Controlling verification of SSL certificates.
225
     *
226
     * @param resource  $curl           CURL resource.
227
     * @param Request   $request        HTTP request params.
228
     */
229 9
    private function triggerDisableSSLCertificateValidation($curl, Request $request)
230
    {
231 9
        if ($request->isDisableSSLValidation()) {
232
            /**
233
             * Disable SSL validation.
234
             */
235 2
            $this
236 2
                ->getAdaptee()
237 2
                ->setopt($curl, CURLOPT_SSL_VERIFYPEER, false)
238 2
                ->setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
239 2
        }
240 9
    }
241
242
    /**
243
     * Controlling request authentication.
244
     *
245
     * @param resource  $curl           CURL resource.
246
     * @param Request   $request        HTTP request params.
247
     */
248 9
    private function triggerAuthentication($curl, Request $request)
249
    {
250 9
        $authentication = $request->getAuthentication();
251 9
        if (!empty($authentication)) {
252
            /**
253
             * Enable authentication.
254
             */
255 9
            $this
256 9
                ->getAdaptee()
257 9
                ->setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY)
258 9
                ->setopt($curl, CURLOPT_USERPWD, $authentication);
259 9
        }
260 9
    }
261
262
    /**
263
     * Sets HTTP headers.
264
     *
265
     * @param resource  $curl       CURL resource.
266
     * @param Request   $request    HTTP request params.
267
     */
268 9
    private function setHedaers($curl, Request $request)
269
    {
270
        /**
271
         * Sets HTTP headers.
272
         */
273 9
        $headers = $this->createBaseHeaderList($request);
274 9
        if (!$this->isPostOrPutRequest($request)) {
275 8
            $headers[] = 'Content-Type: ' . $request->getBodyFormat() . '; charset=utf-8';
276 8
        }
277 9
        $headers = array_merge($headers, $this->createCustomHeaderList($request));
278 9
        $headers = array_merge($headers, $this->createCookieHeaderList($request));
279
280 9
        $this->getAdaptee()->setopt($curl, CURLOPT_HTTPHEADER, $headers);
281 9
    }
282
283
    /**
284
     * Returns the basic set of HTTP headers.
285
     *
286
     * @param Request   $request    HTTP request params.
287
     *
288
     * @return array
289
     */
290 9
    private function createBaseHeaderList(Request $request)
291
    {
292
        return array(
293 9
            'Connection: close',
294 9
            'Accept-Ranges: bytes',
295 9
            'Content-Length: ' . strlen($request->getBody()),
296 9
            'Accept: ' . $request->getBodyFormat() . ',*/*',
297 9
            'User-Agent: ' . $this->getAdaptee()->getAgentString(),
298 9
        );
299
    }
300
301
    /**
302
     * Returns a custom set of HTTP headers.
303
     *
304
     * @param Request   $request    HTTP request params.
305
     *
306
     * @return array
307
     */
308 9
    private function createCustomHeaderList(Request $request)
309
    {
310 9
        $headers = array();
311 9
        foreach ($request->getHeaders() as $header) {
312 9
            $headers[] = $header->toString();
313 9
        }
314 9
        return $headers;
315
    }
316
317
    /**
318
     * Returns the HTTP cookies for the HTTP header.
319
     *
320
     * @param Request   $request    HTTP request params.
321
     *
322
     * @return array
323
     */
324 9
    private function createCookieHeaderList(Request $request)
325
    {
326 9
        $cookies = array();
327 9
        foreach ($request->getCookies() as $cookie) {
328 9
            $cookies[] = $cookie->toString();
329 9
        }
330 9
        $headers = array();
331 9
        if (!empty($cookies)) {
332 9
            $headers[] = 'Cookie: ' . implode('; ', $cookies);
333 9
        }
334 9
        return $headers;
335
    }
336
337
    /**
338
     * Initializing query parameters.
339
     *
340
     * @param Request   $request    HTTP request params.
341
     */
342 9
    private function initParams(Request $request)
343
    {
344 9
        $params = $request->getParams();
345 9
        if (empty($params)) {
346 1
            return;
347
        }
348 8
        $paramsURLEncoded = http_build_query($params);
349 8
        if ($this->isPostOrPutRequest($request)) {
350
            /**
351
             * Adds body parameters.
352
             */
353 1
            $request->setBody($paramsURLEncoded);
354 1
        } else {
355
            /**
356
             * Adds url parameters.
357
             */
358 7
            $request->setUrl($request->getUrl() . '?' . $paramsURLEncoded);
359
        }
360 8
    }
361
}
362