summaryrefslogtreecommitdiffstats
path: root/library/vendor/iplx/Http/Client.php
diff options
context:
space:
mode:
Diffstat (limited to 'library/vendor/iplx/Http/Client.php')
-rw-r--r--library/vendor/iplx/Http/Client.php199
1 files changed, 199 insertions, 0 deletions
diff --git a/library/vendor/iplx/Http/Client.php b/library/vendor/iplx/Http/Client.php
new file mode 100644
index 0000000..39d8905
--- /dev/null
+++ b/library/vendor/iplx/Http/Client.php
@@ -0,0 +1,199 @@
+<?php
+
+namespace iplx\Http;
+
+use RuntimeException;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * HTTP client that uses cURL
+ */
+class Client implements ClientInterface
+{
+ /**
+ * Client version
+ *
+ * @var string
+ */
+ const VERSION = '1.0.0';
+
+ /**
+ * Maximum number of internal cURL handles
+ *
+ * @var int
+ */
+ const MAX_HANDLES = 4;
+
+ /**
+ * Internal cURL handles
+ *
+ * @var array
+ */
+ protected $handles = [];
+
+ /**
+ * Return user agent
+ *
+ * @return string
+ */
+ protected function getAgent()
+ {
+ $defaultAgent = 'ipl/' . self::VERSION;
+ $defaultAgent .= ' curl/' . curl_version()['version'];
+ $defaultAgent .= ' PHP/' . PHP_VERSION;
+
+ return $defaultAgent;
+ }
+
+ /**
+ * Create and return a cURL handle based on the given request
+ *
+ * @param RequestInterface $request
+ * @param array $options
+ *
+ * @return Handle
+ *
+ * @throws RuntimeException
+ */
+ protected function createHandle(RequestInterface $request, array $options)
+ {
+ $headers = [];
+ foreach ($request->getHeaders() as $name => $values) {
+ $headers[] = $name . ': ' . implode(', ', $values);
+ }
+
+ $curlOptions = [
+ CURLOPT_FOLLOWLOCATION => true,
+ CURLOPT_FAILONERROR => true,
+ CURLOPT_USERAGENT => $this->getAgent()
+ ];
+
+ if (isset($options['curl'])) {
+ $curlOptions += $options['curl'];
+ }
+
+ $curlOptions += [
+ CURLOPT_CUSTOMREQUEST => $request->getMethod(),
+ CURLOPT_HTTPHEADER => $headers,
+ CURLOPT_RETURNTRANSFER => false,
+ CURLOPT_URL => (string) $request->getUri()->withFragment('')
+ ];
+
+ if (! $request->hasHeader('Accept')) {
+ $curlOptions[CURLOPT_HTTPHEADER][] = 'Accept:';
+ }
+
+ if (! $request->hasHeader('Content-Type')) {
+ $curlOptions[CURLOPT_HTTPHEADER][] = 'Content-Type:';
+ }
+
+ if (! $request->hasHeader('Expect')) {
+ $curlOptions[CURLOPT_HTTPHEADER][] = 'Expect:';
+ }
+
+ if ($request->getBody()->getSize() !== 0) {
+ $curlOptions[CURLOPT_UPLOAD] = true;
+
+ $body = $request->getBody();
+ if ($body->isSeekable()) {
+ $body->seek(0);
+ }
+
+ $curlOptions[CURLOPT_READFUNCTION] = function ($ch, $infile, $length) use ($body) {
+ return $body->read($length);
+ };
+ }
+
+ if ($request->getProtocolVersion()) {
+ $protocolVersion = null;
+ switch ($request->getProtocolVersion()) {
+ case '2.0':
+ if (version_compare(phpversion(), '7.0.7', '<')) {
+ throw new RuntimeException('You need at least PHP 7.0.7 to use HTTP 2.0');
+ }
+ $protocolVersion = CURL_HTTP_VERSION_2;
+ break;
+ case '1.1':
+ $protocolVersion = CURL_HTTP_VERSION_1_1;
+ break;
+ default:
+ $protocolVersion = CURL_HTTP_VERSION_1_0;
+ }
+
+ $curlOptions[CURLOPT_HTTP_VERSION] = $protocolVersion;
+ }
+
+ $handle = new Handle();
+
+ $curlOptions[CURLOPT_HEADERFUNCTION] = function($ch, $header) use ($handle) {
+ $size = strlen($header);
+
+ if (! trim($header) || strpos($header, 'HTTP/') === 0) {
+ return $size;
+ }
+
+ list($key, $value) = explode(': ', $header, 2);
+ $handle->responseHeaders[$key] = rtrim($value, "\r\n");
+
+ return $size;
+ };
+
+ $handle->responseBody = Stream::open();
+
+ $curlOptions[CURLOPT_WRITEFUNCTION] = function ($ch, $string) use ($handle) {
+ return $handle->responseBody->write($string);
+ };
+
+ $ch = ! empty($this->handles) ? array_pop($this->handles) : curl_init();
+
+ curl_setopt_array($ch, $curlOptions);
+
+ $handle->handle = $ch;
+
+ return $handle;
+ }
+
+ /**
+ * Execute a cURL handle and return the response
+ *
+ * @param Handle $handle
+ *
+ * @return ResponseInterface
+ *
+ * @throws RuntimeException
+ */
+ protected function executeHandle(Handle $handle)
+ {
+ $ch = $handle->handle;
+
+ $success = curl_exec($ch);
+
+ if ($success === false) {
+ throw new RuntimeException(curl_error($ch));
+ }
+
+ $response = new Response(
+ curl_getinfo($ch, CURLINFO_HTTP_CODE), $handle->responseHeaders, $handle->responseBody
+ );
+
+ if (count($this->handles) >= self::MAX_HANDLES) {
+ curl_close($ch);
+ } else {
+ curl_reset($ch);
+
+ $this->handles[] = $ch;
+ }
+
+ return $response;
+ }
+
+ public function send(RequestInterface $request, array $options = [])
+ {
+ $handle = $this->createHandle($request, $options);
+
+ $response = $this->executeHandle($handle);
+
+ return $response;
+ }
+}