These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the Ivory Http Adapter package. |
||
5 | * |
||
6 | * (c) Eric GELOEN <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please read the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | namespace Ivory\HttpAdapter; |
||
13 | |||
14 | use Ivory\HttpAdapter\Extractor\ProtocolVersionExtractor; |
||
15 | use Ivory\HttpAdapter\Extractor\StatusCodeExtractor; |
||
16 | use Ivory\HttpAdapter\Message\InternalRequestInterface; |
||
17 | use Ivory\HttpAdapter\Message\RequestInterface; |
||
18 | use Ivory\HttpAdapter\Normalizer\BodyNormalizer; |
||
19 | use Ivory\HttpAdapter\Normalizer\HeadersNormalizer; |
||
20 | |||
21 | /** |
||
22 | * Curl http adapter. |
||
23 | * |
||
24 | * @author GeLo <[email protected]> |
||
25 | */ |
||
26 | class CurlHttpAdapter extends AbstractCurlHttpAdapter |
||
27 | { |
||
28 | /** |
||
29 | * Creates a curl http adapter. |
||
30 | * |
||
31 | * @param \Ivory\HttpAdapter\ConfigurationInterface|null $configuration The configuration. |
||
32 | */ |
||
33 | 1585 | public function __construct(ConfigurationInterface $configuration = null) |
|
34 | { |
||
35 | 1585 | parent::__construct($configuration); |
|
36 | 1584 | } |
|
37 | |||
38 | /** |
||
39 | * {@inheritdoc} |
||
40 | */ |
||
41 | 91 | public function getName() |
|
42 | { |
||
43 | 91 | return 'curl'; |
|
44 | } |
||
45 | |||
46 | /** |
||
47 | * {@inheritdoc} |
||
48 | */ |
||
49 | 1476 | protected function sendInternalRequest(InternalRequestInterface $internalRequest) |
|
50 | { |
||
51 | 1476 | $curl = $this->createCurl($internalRequest); |
|
52 | |||
53 | try { |
||
54 | 1476 | $response = $this->createResponse($curl, curl_exec($curl), $internalRequest); |
|
55 | 1397 | } catch (HttpAdapterException $e) { |
|
56 | 54 | curl_close($curl); |
|
57 | |||
58 | 54 | throw $e; |
|
59 | } |
||
60 | |||
61 | 1422 | curl_close($curl); |
|
62 | |||
63 | 1422 | return $response; |
|
64 | } |
||
65 | |||
66 | /** |
||
67 | * {@inheritdoc} |
||
68 | */ |
||
69 | 36 | protected function sendInternalRequests(array $internalRequests, $success, $error) |
|
70 | { |
||
71 | 36 | $curlMulti = curl_multi_init(); |
|
72 | |||
73 | 36 | $contexts = array(); |
|
74 | 36 | foreach ($internalRequests as $internalRequest) { |
|
75 | 36 | $contexts[] = array( |
|
76 | 36 | 'curl' => $curl = $this->createCurl($internalRequest), |
|
77 | 36 | 'request' => $internalRequest, |
|
78 | ); |
||
79 | |||
80 | 36 | curl_multi_add_handle($curlMulti, $curl); |
|
81 | 34 | } |
|
82 | |||
83 | do { |
||
84 | do { |
||
85 | 36 | $exec = curl_multi_exec($curlMulti, $running); |
|
86 | 36 | } while ($exec === CURLM_CALL_MULTI_PERFORM); |
|
87 | |||
88 | 36 | while ($done = curl_multi_info_read($curlMulti)) { |
|
89 | 36 | $curl = $done['handle']; |
|
90 | 36 | $internalRequest = $this->resolveInternalRequest($curl, $contexts); |
|
91 | |||
92 | try { |
||
93 | 36 | $response = $this->createResponse($curl, curl_multi_getcontent($curl), $internalRequest); |
|
94 | 36 | $response = $response->withParameter('request', $internalRequest); |
|
95 | 36 | call_user_func($success, $response); |
|
96 | 35 | } catch (HttpAdapterException $e) { |
|
97 | 18 | $e->setRequest($internalRequest); |
|
98 | 18 | call_user_func($error, $e); |
|
99 | } |
||
100 | |||
101 | 36 | curl_multi_remove_handle($curlMulti, $curl); |
|
102 | 36 | curl_close($curl); |
|
103 | 34 | } |
|
104 | 36 | } while ($running); |
|
105 | |||
106 | 36 | curl_multi_close($curlMulti); |
|
107 | 36 | } |
|
108 | |||
109 | /** |
||
110 | * Creates a curl resource. |
||
111 | * |
||
112 | * @param \Ivory\HttpAdapter\Message\InternalRequestInterface $internalRequest The internal request. |
||
113 | * |
||
114 | * @return resource The curl resource. |
||
115 | */ |
||
116 | 1512 | private function createCurl(InternalRequestInterface $internalRequest) |
|
117 | { |
||
118 | 1512 | $curl = curl_init(); |
|
119 | |||
120 | 1512 | curl_setopt($curl, CURLOPT_URL, (string) $internalRequest->getUri()); |
|
121 | 1512 | curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); |
|
122 | 1512 | curl_setopt($curl, CURLOPT_HTTP_VERSION, $this->prepareProtocolVersion($internalRequest)); |
|
123 | 1512 | curl_setopt($curl, CURLOPT_HEADER, true); |
|
124 | 1512 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); |
|
125 | 1512 | curl_setopt($curl, CURLOPT_HTTPHEADER, $this->prepareHeaders($internalRequest, false, false)); |
|
126 | |||
127 | 1512 | $this->configureTimeout($curl, 'CURLOPT_TIMEOUT'); |
|
128 | 1512 | $this->configureTimeout($curl, 'CURLOPT_CONNECTTIMEOUT'); |
|
129 | |||
130 | 1512 | $files = $internalRequest->getFiles(); |
|
131 | |||
132 | 1512 | if (!empty($files) && $this->isSafeUpload()) { |
|
133 | 160 | curl_setopt($curl, CURLOPT_SAFE_UPLOAD, true); |
|
134 | 150 | } |
|
135 | |||
136 | 1512 | switch ($internalRequest->getMethod()) { |
|
137 | 1512 | case RequestInterface::METHOD_HEAD: |
|
138 | 144 | curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $internalRequest->getMethod()); |
|
139 | 144 | curl_setopt($curl, CURLOPT_NOBODY, true); |
|
140 | 144 | break; |
|
141 | |||
142 | 1404 | case RequestInterface::METHOD_TRACE: |
|
143 | 144 | curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $internalRequest->getMethod()); |
|
144 | 144 | break; |
|
145 | |||
146 | 1296 | View Code Duplication | case RequestInterface::METHOD_POST: |
147 | 252 | curl_setopt($curl, CURLOPT_POST, true); |
|
148 | 252 | curl_setopt($curl, CURLOPT_POSTFIELDS, $this->prepareContent($internalRequest)); |
|
149 | 252 | break; |
|
150 | |||
151 | 1080 | case RequestInterface::METHOD_PUT: |
|
152 | 1069 | case RequestInterface::METHOD_PATCH: |
|
153 | 1058 | case RequestInterface::METHOD_DELETE: |
|
154 | 1047 | View Code Duplication | case RequestInterface::METHOD_OPTIONS: |
155 | 828 | curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $internalRequest->getMethod()); |
|
156 | 828 | curl_setopt($curl, CURLOPT_POSTFIELDS, $this->prepareContent($internalRequest)); |
|
157 | 828 | break; |
|
158 | 1428 | } |
|
159 | |||
160 | 1512 | return $curl; |
|
161 | } |
||
162 | |||
163 | /** |
||
164 | * Configures a timeout. |
||
165 | * |
||
166 | * @param resource $curl The curl resource. |
||
167 | * @param string $type The timeout type. |
||
168 | */ |
||
169 | 1512 | private function configureTimeout($curl, $type) |
|
170 | { |
||
171 | 1512 | if (defined($type.'_MS')) { |
|
172 | 1512 | curl_setopt($curl, constant($type.'_MS'), $this->getConfiguration()->getTimeout() * 1000); |
|
173 | } else { // @codeCoverageIgnoreStart |
||
174 | curl_setopt($curl, constant($type), $this->getConfiguration()->getTimeout()); |
||
175 | } // @codeCoverageIgnoreEnd |
||
176 | 1512 | } |
|
177 | |||
178 | /** |
||
179 | * Creates a response. |
||
180 | * |
||
181 | * @param resource $curl The curl resource. |
||
182 | * @param string|boolean|null $data The data. |
||
183 | * @param \Ivory\HttpAdapter\Message\InternalRequestInterface $internalRequest The internal request. |
||
184 | * |
||
185 | * @throws \Ivory\HttpAdapter\HttpAdapterException If an error occurred. |
||
186 | * |
||
187 | * @return \Ivory\HttpAdapter\Message\ResponseInterface The response. |
||
188 | */ |
||
189 | 1512 | private function createResponse($curl, $data, InternalRequestInterface $internalRequest) |
|
190 | { |
||
191 | 1512 | if (empty($data)) { |
|
192 | 72 | throw HttpAdapterException::cannotFetchUri( |
|
193 | 72 | (string) $internalRequest->getUri(), |
|
194 | 72 | $this->getName(), |
|
195 | 68 | curl_error($curl) |
|
196 | 68 | ); |
|
197 | } |
||
198 | |||
199 | 1458 | $headers = substr($data, 0, $headersSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE)); |
|
200 | |||
201 | 1458 | return $this->getConfiguration()->getMessageFactory()->createResponse( |
|
202 | 1458 | StatusCodeExtractor::extract($headers), |
|
203 | 1458 | ProtocolVersionExtractor::extract($headers), |
|
204 | 1458 | HeadersNormalizer::normalize($headers), |
|
205 | 1458 | BodyNormalizer::normalize(substr($data, $headersSize), $internalRequest->getMethod()) |
|
206 | 1377 | ); |
|
207 | } |
||
208 | |||
209 | /** |
||
210 | * Resolves the internal request. |
||
211 | * |
||
212 | * @param resource $curl The curl resource. |
||
213 | * @param array $contexts The contexts. |
||
214 | * |
||
215 | * @return \Ivory\HttpAdapter\Message\InternalRequestInterface The internal request. |
||
216 | */ |
||
217 | 36 | private function resolveInternalRequest($curl, array $contexts) |
|
218 | { |
||
219 | 36 | foreach ($contexts as $context) { |
|
220 | 36 | if ($context['curl'] === $curl) { |
|
221 | 36 | break; |
|
222 | } |
||
223 | 34 | } |
|
224 | |||
225 | 36 | return $context['request']; |
|
0 ignored issues
–
show
|
|||
226 | } |
||
227 | } |
||
228 |
It seems like you are relying on a variable being defined by an iteration: