Chris@0
|
1 <?php
|
Chris@0
|
2 namespace GuzzleHttp;
|
Chris@0
|
3
|
Chris@0
|
4 use GuzzleHttp\Handler\CurlHandler;
|
Chris@0
|
5 use GuzzleHttp\Handler\CurlMultiHandler;
|
Chris@0
|
6 use GuzzleHttp\Handler\Proxy;
|
Chris@0
|
7 use GuzzleHttp\Handler\StreamHandler;
|
Chris@0
|
8
|
Chris@0
|
9 /**
|
Chris@0
|
10 * Expands a URI template
|
Chris@0
|
11 *
|
Chris@0
|
12 * @param string $template URI template
|
Chris@0
|
13 * @param array $variables Template variables
|
Chris@0
|
14 *
|
Chris@0
|
15 * @return string
|
Chris@0
|
16 */
|
Chris@0
|
17 function uri_template($template, array $variables)
|
Chris@0
|
18 {
|
Chris@0
|
19 if (extension_loaded('uri_template')) {
|
Chris@0
|
20 // @codeCoverageIgnoreStart
|
Chris@0
|
21 return \uri_template($template, $variables);
|
Chris@0
|
22 // @codeCoverageIgnoreEnd
|
Chris@0
|
23 }
|
Chris@0
|
24
|
Chris@0
|
25 static $uriTemplate;
|
Chris@0
|
26 if (!$uriTemplate) {
|
Chris@0
|
27 $uriTemplate = new UriTemplate();
|
Chris@0
|
28 }
|
Chris@0
|
29
|
Chris@0
|
30 return $uriTemplate->expand($template, $variables);
|
Chris@0
|
31 }
|
Chris@0
|
32
|
Chris@0
|
33 /**
|
Chris@0
|
34 * Debug function used to describe the provided value type and class.
|
Chris@0
|
35 *
|
Chris@0
|
36 * @param mixed $input
|
Chris@0
|
37 *
|
Chris@0
|
38 * @return string Returns a string containing the type of the variable and
|
Chris@0
|
39 * if a class is provided, the class name.
|
Chris@0
|
40 */
|
Chris@0
|
41 function describe_type($input)
|
Chris@0
|
42 {
|
Chris@0
|
43 switch (gettype($input)) {
|
Chris@0
|
44 case 'object':
|
Chris@0
|
45 return 'object(' . get_class($input) . ')';
|
Chris@0
|
46 case 'array':
|
Chris@0
|
47 return 'array(' . count($input) . ')';
|
Chris@0
|
48 default:
|
Chris@0
|
49 ob_start();
|
Chris@0
|
50 var_dump($input);
|
Chris@0
|
51 // normalize float vs double
|
Chris@0
|
52 return str_replace('double(', 'float(', rtrim(ob_get_clean()));
|
Chris@0
|
53 }
|
Chris@0
|
54 }
|
Chris@0
|
55
|
Chris@0
|
56 /**
|
Chris@0
|
57 * Parses an array of header lines into an associative array of headers.
|
Chris@0
|
58 *
|
Chris@0
|
59 * @param array $lines Header lines array of strings in the following
|
Chris@0
|
60 * format: "Name: Value"
|
Chris@0
|
61 * @return array
|
Chris@0
|
62 */
|
Chris@0
|
63 function headers_from_lines($lines)
|
Chris@0
|
64 {
|
Chris@0
|
65 $headers = [];
|
Chris@0
|
66
|
Chris@0
|
67 foreach ($lines as $line) {
|
Chris@0
|
68 $parts = explode(':', $line, 2);
|
Chris@0
|
69 $headers[trim($parts[0])][] = isset($parts[1])
|
Chris@0
|
70 ? trim($parts[1])
|
Chris@0
|
71 : null;
|
Chris@0
|
72 }
|
Chris@0
|
73
|
Chris@0
|
74 return $headers;
|
Chris@0
|
75 }
|
Chris@0
|
76
|
Chris@0
|
77 /**
|
Chris@0
|
78 * Returns a debug stream based on the provided variable.
|
Chris@0
|
79 *
|
Chris@0
|
80 * @param mixed $value Optional value
|
Chris@0
|
81 *
|
Chris@0
|
82 * @return resource
|
Chris@0
|
83 */
|
Chris@0
|
84 function debug_resource($value = null)
|
Chris@0
|
85 {
|
Chris@0
|
86 if (is_resource($value)) {
|
Chris@0
|
87 return $value;
|
Chris@0
|
88 } elseif (defined('STDOUT')) {
|
Chris@0
|
89 return STDOUT;
|
Chris@0
|
90 }
|
Chris@0
|
91
|
Chris@0
|
92 return fopen('php://output', 'w');
|
Chris@0
|
93 }
|
Chris@0
|
94
|
Chris@0
|
95 /**
|
Chris@0
|
96 * Chooses and creates a default handler to use based on the environment.
|
Chris@0
|
97 *
|
Chris@0
|
98 * The returned handler is not wrapped by any default middlewares.
|
Chris@0
|
99 *
|
Chris@0
|
100 * @throws \RuntimeException if no viable Handler is available.
|
Chris@0
|
101 * @return callable Returns the best handler for the given system.
|
Chris@0
|
102 */
|
Chris@0
|
103 function choose_handler()
|
Chris@0
|
104 {
|
Chris@0
|
105 $handler = null;
|
Chris@0
|
106 if (function_exists('curl_multi_exec') && function_exists('curl_exec')) {
|
Chris@0
|
107 $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
|
Chris@0
|
108 } elseif (function_exists('curl_exec')) {
|
Chris@0
|
109 $handler = new CurlHandler();
|
Chris@0
|
110 } elseif (function_exists('curl_multi_exec')) {
|
Chris@0
|
111 $handler = new CurlMultiHandler();
|
Chris@0
|
112 }
|
Chris@0
|
113
|
Chris@0
|
114 if (ini_get('allow_url_fopen')) {
|
Chris@0
|
115 $handler = $handler
|
Chris@0
|
116 ? Proxy::wrapStreaming($handler, new StreamHandler())
|
Chris@0
|
117 : new StreamHandler();
|
Chris@0
|
118 } elseif (!$handler) {
|
Chris@0
|
119 throw new \RuntimeException('GuzzleHttp requires cURL, the '
|
Chris@0
|
120 . 'allow_url_fopen ini setting, or a custom HTTP handler.');
|
Chris@0
|
121 }
|
Chris@0
|
122
|
Chris@0
|
123 return $handler;
|
Chris@0
|
124 }
|
Chris@0
|
125
|
Chris@0
|
126 /**
|
Chris@0
|
127 * Get the default User-Agent string to use with Guzzle
|
Chris@0
|
128 *
|
Chris@0
|
129 * @return string
|
Chris@0
|
130 */
|
Chris@0
|
131 function default_user_agent()
|
Chris@0
|
132 {
|
Chris@0
|
133 static $defaultAgent = '';
|
Chris@0
|
134
|
Chris@0
|
135 if (!$defaultAgent) {
|
Chris@0
|
136 $defaultAgent = 'GuzzleHttp/' . Client::VERSION;
|
Chris@0
|
137 if (extension_loaded('curl') && function_exists('curl_version')) {
|
Chris@0
|
138 $defaultAgent .= ' curl/' . \curl_version()['version'];
|
Chris@0
|
139 }
|
Chris@0
|
140 $defaultAgent .= ' PHP/' . PHP_VERSION;
|
Chris@0
|
141 }
|
Chris@0
|
142
|
Chris@0
|
143 return $defaultAgent;
|
Chris@0
|
144 }
|
Chris@0
|
145
|
Chris@0
|
146 /**
|
Chris@0
|
147 * Returns the default cacert bundle for the current system.
|
Chris@0
|
148 *
|
Chris@0
|
149 * First, the openssl.cafile and curl.cainfo php.ini settings are checked.
|
Chris@0
|
150 * If those settings are not configured, then the common locations for
|
Chris@0
|
151 * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
|
Chris@0
|
152 * and Windows are checked. If any of these file locations are found on
|
Chris@0
|
153 * disk, they will be utilized.
|
Chris@0
|
154 *
|
Chris@0
|
155 * Note: the result of this function is cached for subsequent calls.
|
Chris@0
|
156 *
|
Chris@0
|
157 * @return string
|
Chris@0
|
158 * @throws \RuntimeException if no bundle can be found.
|
Chris@0
|
159 */
|
Chris@0
|
160 function default_ca_bundle()
|
Chris@0
|
161 {
|
Chris@0
|
162 static $cached = null;
|
Chris@0
|
163 static $cafiles = [
|
Chris@0
|
164 // Red Hat, CentOS, Fedora (provided by the ca-certificates package)
|
Chris@0
|
165 '/etc/pki/tls/certs/ca-bundle.crt',
|
Chris@0
|
166 // Ubuntu, Debian (provided by the ca-certificates package)
|
Chris@0
|
167 '/etc/ssl/certs/ca-certificates.crt',
|
Chris@0
|
168 // FreeBSD (provided by the ca_root_nss package)
|
Chris@0
|
169 '/usr/local/share/certs/ca-root-nss.crt',
|
Chris@0
|
170 // SLES 12 (provided by the ca-certificates package)
|
Chris@0
|
171 '/var/lib/ca-certificates/ca-bundle.pem',
|
Chris@0
|
172 // OS X provided by homebrew (using the default path)
|
Chris@0
|
173 '/usr/local/etc/openssl/cert.pem',
|
Chris@0
|
174 // Google app engine
|
Chris@0
|
175 '/etc/ca-certificates.crt',
|
Chris@0
|
176 // Windows?
|
Chris@0
|
177 'C:\\windows\\system32\\curl-ca-bundle.crt',
|
Chris@0
|
178 'C:\\windows\\curl-ca-bundle.crt',
|
Chris@0
|
179 ];
|
Chris@0
|
180
|
Chris@0
|
181 if ($cached) {
|
Chris@0
|
182 return $cached;
|
Chris@0
|
183 }
|
Chris@0
|
184
|
Chris@0
|
185 if ($ca = ini_get('openssl.cafile')) {
|
Chris@0
|
186 return $cached = $ca;
|
Chris@0
|
187 }
|
Chris@0
|
188
|
Chris@0
|
189 if ($ca = ini_get('curl.cainfo')) {
|
Chris@0
|
190 return $cached = $ca;
|
Chris@0
|
191 }
|
Chris@0
|
192
|
Chris@0
|
193 foreach ($cafiles as $filename) {
|
Chris@0
|
194 if (file_exists($filename)) {
|
Chris@0
|
195 return $cached = $filename;
|
Chris@0
|
196 }
|
Chris@0
|
197 }
|
Chris@0
|
198
|
Chris@0
|
199 throw new \RuntimeException(<<< EOT
|
Chris@0
|
200 No system CA bundle could be found in any of the the common system locations.
|
Chris@0
|
201 PHP versions earlier than 5.6 are not properly configured to use the system's
|
Chris@0
|
202 CA bundle by default. In order to verify peer certificates, you will need to
|
Chris@0
|
203 supply the path on disk to a certificate bundle to the 'verify' request
|
Chris@0
|
204 option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not
|
Chris@0
|
205 need a specific certificate bundle, then Mozilla provides a commonly used CA
|
Chris@0
|
206 bundle which can be downloaded here (provided by the maintainer of cURL):
|
Chris@0
|
207 https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once
|
Chris@0
|
208 you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
|
Chris@0
|
209 ini setting to point to the path to the file, allowing you to omit the 'verify'
|
Chris@0
|
210 request option. See http://curl.haxx.se/docs/sslcerts.html for more
|
Chris@0
|
211 information.
|
Chris@0
|
212 EOT
|
Chris@0
|
213 );
|
Chris@0
|
214 }
|
Chris@0
|
215
|
Chris@0
|
216 /**
|
Chris@0
|
217 * Creates an associative array of lowercase header names to the actual
|
Chris@0
|
218 * header casing.
|
Chris@0
|
219 *
|
Chris@0
|
220 * @param array $headers
|
Chris@0
|
221 *
|
Chris@0
|
222 * @return array
|
Chris@0
|
223 */
|
Chris@0
|
224 function normalize_header_keys(array $headers)
|
Chris@0
|
225 {
|
Chris@0
|
226 $result = [];
|
Chris@0
|
227 foreach (array_keys($headers) as $key) {
|
Chris@0
|
228 $result[strtolower($key)] = $key;
|
Chris@0
|
229 }
|
Chris@0
|
230
|
Chris@0
|
231 return $result;
|
Chris@0
|
232 }
|
Chris@0
|
233
|
Chris@0
|
234 /**
|
Chris@0
|
235 * Returns true if the provided host matches any of the no proxy areas.
|
Chris@0
|
236 *
|
Chris@0
|
237 * This method will strip a port from the host if it is present. Each pattern
|
Chris@0
|
238 * can be matched with an exact match (e.g., "foo.com" == "foo.com") or a
|
Chris@0
|
239 * partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" ==
|
Chris@0
|
240 * "baz.foo.com", but ".foo.com" != "foo.com").
|
Chris@0
|
241 *
|
Chris@0
|
242 * Areas are matched in the following cases:
|
Chris@0
|
243 * 1. "*" (without quotes) always matches any hosts.
|
Chris@0
|
244 * 2. An exact match.
|
Chris@0
|
245 * 3. The area starts with "." and the area is the last part of the host. e.g.
|
Chris@0
|
246 * '.mit.edu' will match any host that ends with '.mit.edu'.
|
Chris@0
|
247 *
|
Chris@0
|
248 * @param string $host Host to check against the patterns.
|
Chris@0
|
249 * @param array $noProxyArray An array of host patterns.
|
Chris@0
|
250 *
|
Chris@0
|
251 * @return bool
|
Chris@0
|
252 */
|
Chris@0
|
253 function is_host_in_noproxy($host, array $noProxyArray)
|
Chris@0
|
254 {
|
Chris@0
|
255 if (strlen($host) === 0) {
|
Chris@0
|
256 throw new \InvalidArgumentException('Empty host provided');
|
Chris@0
|
257 }
|
Chris@0
|
258
|
Chris@0
|
259 // Strip port if present.
|
Chris@0
|
260 if (strpos($host, ':')) {
|
Chris@0
|
261 $host = explode($host, ':', 2)[0];
|
Chris@0
|
262 }
|
Chris@0
|
263
|
Chris@0
|
264 foreach ($noProxyArray as $area) {
|
Chris@0
|
265 // Always match on wildcards.
|
Chris@0
|
266 if ($area === '*') {
|
Chris@0
|
267 return true;
|
Chris@0
|
268 } elseif (empty($area)) {
|
Chris@0
|
269 // Don't match on empty values.
|
Chris@0
|
270 continue;
|
Chris@0
|
271 } elseif ($area === $host) {
|
Chris@0
|
272 // Exact matches.
|
Chris@0
|
273 return true;
|
Chris@0
|
274 } else {
|
Chris@0
|
275 // Special match if the area when prefixed with ".". Remove any
|
Chris@0
|
276 // existing leading "." and add a new leading ".".
|
Chris@0
|
277 $area = '.' . ltrim($area, '.');
|
Chris@0
|
278 if (substr($host, -(strlen($area))) === $area) {
|
Chris@0
|
279 return true;
|
Chris@0
|
280 }
|
Chris@0
|
281 }
|
Chris@0
|
282 }
|
Chris@0
|
283
|
Chris@0
|
284 return false;
|
Chris@0
|
285 }
|
Chris@0
|
286
|
Chris@0
|
287 /**
|
Chris@0
|
288 * Wrapper for json_decode that throws when an error occurs.
|
Chris@0
|
289 *
|
Chris@0
|
290 * @param string $json JSON data to parse
|
Chris@0
|
291 * @param bool $assoc When true, returned objects will be converted
|
Chris@0
|
292 * into associative arrays.
|
Chris@0
|
293 * @param int $depth User specified recursion depth.
|
Chris@0
|
294 * @param int $options Bitmask of JSON decode options.
|
Chris@0
|
295 *
|
Chris@0
|
296 * @return mixed
|
Chris@0
|
297 * @throws \InvalidArgumentException if the JSON cannot be decoded.
|
Chris@0
|
298 * @link http://www.php.net/manual/en/function.json-decode.php
|
Chris@0
|
299 */
|
Chris@0
|
300 function json_decode($json, $assoc = false, $depth = 512, $options = 0)
|
Chris@0
|
301 {
|
Chris@0
|
302 $data = \json_decode($json, $assoc, $depth, $options);
|
Chris@0
|
303 if (JSON_ERROR_NONE !== json_last_error()) {
|
Chris@0
|
304 throw new \InvalidArgumentException(
|
Chris@13
|
305 'json_decode error: ' . json_last_error_msg()
|
Chris@13
|
306 );
|
Chris@0
|
307 }
|
Chris@0
|
308
|
Chris@0
|
309 return $data;
|
Chris@0
|
310 }
|
Chris@0
|
311
|
Chris@0
|
312 /**
|
Chris@0
|
313 * Wrapper for JSON encoding that throws when an error occurs.
|
Chris@0
|
314 *
|
Chris@0
|
315 * @param mixed $value The value being encoded
|
Chris@0
|
316 * @param int $options JSON encode option bitmask
|
Chris@0
|
317 * @param int $depth Set the maximum depth. Must be greater than zero.
|
Chris@0
|
318 *
|
Chris@0
|
319 * @return string
|
Chris@0
|
320 * @throws \InvalidArgumentException if the JSON cannot be encoded.
|
Chris@0
|
321 * @link http://www.php.net/manual/en/function.json-encode.php
|
Chris@0
|
322 */
|
Chris@0
|
323 function json_encode($value, $options = 0, $depth = 512)
|
Chris@0
|
324 {
|
Chris@0
|
325 $json = \json_encode($value, $options, $depth);
|
Chris@0
|
326 if (JSON_ERROR_NONE !== json_last_error()) {
|
Chris@0
|
327 throw new \InvalidArgumentException(
|
Chris@13
|
328 'json_encode error: ' . json_last_error_msg()
|
Chris@13
|
329 );
|
Chris@0
|
330 }
|
Chris@0
|
331
|
Chris@0
|
332 return $json;
|
Chris@0
|
333 }
|