Completed
Pull Request — master (#65)
by Timothée
05:28
created

RestApiBrowser::removeRequestHeader()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 1
1
<?php
2
3
namespace Rezzza\RestApiBehatExtension\Rest;
4
5
use Http\Client\HttpClient;
6
use Http\Discovery\HttpClientDiscovery;
7
use Http\Discovery\MessageFactoryDiscovery;
8
use Psr\Http\Message\RequestInterface;
9
use Psr\Http\Message\ResponseInterface;
10
use Tolerance\Operation\Callback;
11
use Tolerance\Operation\Runner\RetryOperationRunner;
12
use Tolerance\Operation\Runner\CallbackOperationRunner;
13
use Tolerance\Waiter\SleepWaiter;
14
use Rezzza\RestApiBehatExtension\Tolerance\ExecutionTimeLimited;
15
16
class RestApiBrowser
17
{
18
    /** @var HttpClient */
19
    private $httpClient;
20
21
    /** @var RequestInterface */
22
    private $request;
23
24
    /** @var ResponseInterface */
25
    private $response;
26
27
    /** @var array */
28
    private $requestHeaders = [];
29
30
    /** @var ResponseStorage */
31
    private $responseStorage;
32
33
    /** @var string */
34
    private $host;
35
36
    /** @var MessageFactoryDiscovery */
37
    private $messageFactory;
38
39
    /**
40
     * @param string $host
41
     */
42
    public function __construct($host, HttpClient $httpClient = null)
43
    {
44
        $this->host = $host;
45
        $this->httpClient = $httpClient ?: HttpClientDiscovery::find();
46
        $this->messageFactory = MessageFactoryDiscovery::find();
0 ignored issues
show
Documentation Bug introduced by
It seems like \Http\Discovery\MessageFactoryDiscovery::find() of type object<Http\Message\MessageFactory> is incompatible with the declared type object<Http\Discovery\MessageFactoryDiscovery> of property $messageFactory.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
47
    }
48
49
    /**
50
     * Allow to override the httpClient to use yours with specific middleware for example
51
     */
52
    public function useHttpClient(HttpClient $httpClient)
53
    {
54
        $this->httpClient = $httpClient;
55
    }
56
57
    /**
58
     * @param ResponseStorage $responseStorage
59
     */
60
    public function enableResponseStorage(ResponseStorage $responseStorage)
61
    {
62
        $this->responseStorage = $responseStorage;
63
    }
64
65
    /**
66
     * @return ResponseInterface
67
     */
68
    public function getResponse()
69
    {
70
        return $this->response;
71
    }
72
73
    /**
74
     * @param ResponseInterface $response
75
     */
76
    public function setResponse(ResponseInterface $response)
77
    {
78
        $this->response = $response;
79
    }
80
81
    public function getRequest()
82
    {
83
        return $this->request;
84
    }
85
86
    public function getRequestHeaders()
87
    {
88
        return $this->requestHeaders;
89
    }
90
91
    /**
92
     * @param string $method
93
     * @param string $uri
94
     * @param string|array $body
95
     */
96
    public function sendRequest($method, $uri, $body = null)
97
    {
98
        $this->doSendRequest($method, $uri, $body);
99
        $this->clearRequestHeaders();
100
    }
101
102
    public function sendRequestUntil($method, $uri, $body, callable $assertion, $maxExecutionTime = 10)
103
    {
104
        $runner = new RetryOperationRunner(
105
            new CallbackOperationRunner(),
106
            new ExecutionTimeLimited(new SleepWaiter(), $maxExecutionTime)
107
        );
108
        $restApiBrowser = $this;
109
        $runner->run(new Callback(function () use ($restApiBrowser, $method, $uri, $body, $assertion) {
110
            $restApiBrowser->doSendRequest($method, $uri, $body);
111
112
            return $assertion();
113
        }));
114
        $this->clearRequestHeaders();
115
    }
116
117
    /**
118
     * @param string $name
119
     * @param string $value
120
     */
121
    public function setRequestHeader($name, $value)
122
    {
123
        $this->removeRequestHeader($name);
124
        $this->addRequestHeader($name, $value);
125
    }
126
127
    /**
128
     * @param string $name
129
     * @param string $value
130
     */
131
    public function addRequestHeader($name, $value)
132
    {
133
        if (isset($this->requestHeaders[$name])) {
134
            $this->requestHeaders[$name] .= ', '.$value;
135
        } else {
136
            $this->requestHeaders[$name] = $value;
137
        }
138
    }
139
140
    /**
141
     * @param string $headerName
142
     */
143
    private function removeRequestHeader($headerName)
144
    {
145
        if (array_key_exists($headerName, $this->requestHeaders)) {
146
            unset($this->requestHeaders[$headerName]);
147
        }
148
    }
149
150
    /**
151
     * @param string $uri
152
     *
153
     * @return bool
154
     */
155
    private function hasHost($uri)
156
    {
157
        return strpos($uri, '://') !== false;
158
    }
159
160
    private function doSendRequest($method, $uri, $body)
161
    {
162
        if (false === $this->hasHost($uri)) {
163
            $uri = rtrim($this->host, '/').'/'.ltrim($uri, '/');
164
        }
165
166
        $this->request = $this->messageFactory->createRequest($method, $uri, $this->requestHeaders, $body);
0 ignored issues
show
Bug introduced by
The method createRequest() does not seem to exist on object<Http\Discovery\MessageFactoryDiscovery>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
167
        $this->response = $this->httpClient->sendRequest($this->request);
168
169
        if (null !== $this->responseStorage) {
170
            $this->responseStorage->writeRawContent((string) $this->response->getBody());
171
        }
172
    }
173
174
    private function clearRequestHeaders()
175
    {
176
        // Definitively needed to ensure context isolation for each request.
177
        $this->requestHeaders = [];
178
    }
179
}
180