CurlHttpRunner::addRequest()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
namespace DjThossi\SmokeTestingPhp\Runner;
3
4
use Curl\CaseInsensitiveArray;
5
use Curl\Curl;
6
use Curl\MultiCurl;
7
use DjThossi\SmokeTestingPhp\Collection\ResultCollection;
8
use DjThossi\SmokeTestingPhp\Options\RequestOptions;
9
use DjThossi\SmokeTestingPhp\Result\ErrorResult;
10
use DjThossi\SmokeTestingPhp\Result\ValidResult;
11
use DjThossi\SmokeTestingPhp\ValueObject\BodyLength;
12
use DjThossi\SmokeTestingPhp\ValueObject\Concurrency;
13
14
class CurlHttpRunner implements HttpRunner
15
{
16
    /**
17
     * @var BodyLength
18
     */
19
    private $bodyLength;
20
21
    /**
22
     * @var MultiCurl
23
     */
24
    private $multiCurl;
25
26
    /**
27
     * @var ResultCollection
28
     */
29
    private $results;
30
31
    /**
32
     * @var callable
33
     */
34
    private $successCallback;
35
36
    /**
37
     * @var callable
38
     */
39
    private $errorCallback;
40
41
    /**
42
     * @param Concurrency $concurrency
43
     * @param BodyLength $bodyLength
44
     * @param callable $successCallback
45
     * @param callable $errorCallback
46
     */
47
    public function __construct(
48
        Concurrency $concurrency,
49
        BodyLength $bodyLength,
50
        callable $successCallback,
51
        callable $errorCallback
52
    ) {
53
        $this->multiCurl = new MultiCurl();
54
        $this->multiCurl->setConcurrency($concurrency->asInteger());
55
        $this->multiCurl->success([$this, 'onSuccess']);
56
        $this->multiCurl->error([$this, 'onError']);
57
        $this->bodyLength = $bodyLength;
58
        $this->successCallback = $successCallback;
59
        $this->errorCallback = $errorCallback;
60
    }
61
62
    /**
63
     * @param RequestOptions $requestOptions
64
     */
65
    public function addRequest(RequestOptions $requestOptions)
66
    {
67
        $curl = new Curl();
68
        $curl->setUrl($requestOptions->getUrl()->asString());
69
        $curl->setTimeout($requestOptions->getRequestTimeout()->inSeconds());
70
        $curl->setOpt(CURLOPT_FOLLOWLOCATION, $requestOptions->getFollowRedirect()->asBoolean());
71
72
        if ($requestOptions->needsBasicAuth()) {
73
            $curl->setBasicAuthentication(
74
                $requestOptions->getBasicAuth()->getUsername(),
75
                $requestOptions->getBasicAuth()->getPassword()
76
            );
77
        }
78
79
        $this->multiCurl->addCurl($curl);
80
    }
81
82
    /**
83
     * @return ResultCollection
84
     */
85
    public function run()
86
    {
87
        $this->results = new ResultCollection();
88
        $this->multiCurl->start();
89
90
        return $this->results;
91
    }
92
93
    /**
94
     * @param Curl $curl
95
     */
96
    public function onSuccess(Curl $curl)
97
    {
98
        $curlInfo = $curl->getInfo();
99
        $timeToFirstByte = $curlInfo['starttransfer_time'] - $curlInfo['pretransfer_time'];
100
        $ttfbInMilliseconds = (int) round($timeToFirstByte * 1000);
101
102
        $body = substr($curl->response, 0, $this->bodyLength->asInteger());
103
104
        $validResult = ValidResult::fromPrimitives(
105
            $curl->url,
106
            $this->convertHeadersToArray($curl->responseHeaders),
107
            $body,
108
            $ttfbInMilliseconds,
109
            $curl->httpStatusCode
110
        );
111
112
        \call_user_func($this->successCallback, $validResult);
113
114
        $this->results->addResult($validResult);
115
    }
116
117
    /**
118
     * @param Curl $curl
119
     */
120
    public function onError(Curl $curl)
121
    {
122
        $errorMessage = sprintf(
123
            'Curl Code: %s Error: %s',
124
            $curl->errorCode,
125
            $curl->errorMessage
126
        );
127
128
        $errorResult = ErrorResult::fromPrimitives(
129
            $curl->url,
130
            $this->convertHeadersToArray($curl->responseHeaders),
131
            $errorMessage
132
        );
133
134
        \call_user_func($this->errorCallback, $errorResult);
135
136
        $this->results->addResult($errorResult);
137
    }
138
139
    /**
140
     * @param CaseInsensitiveArray $headers
141
     *
142
     * @return array
143
     */
144
    private function convertHeadersToArray(CaseInsensitiveArray $headers)
145
    {
146
        $headerData = [];
147
        foreach ($headers as $key => $value) {
148
            $headerData[$key] = trim($value);
149
        }
150
151
        return $headerData;
152
    }
153
}
154