| | <?php |
| |
|
| | namespace JsonRPC; |
| |
|
| | use Closure; |
| | use JsonRPC\Exception\AccessDeniedException; |
| | use JsonRPC\Exception\ConnectionFailureException; |
| | use JsonRPC\Exception\ServerErrorException; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | class HttpClient |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| | protected $url; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | protected $timeout = 5; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | protected $headers = array( |
| | 'User-Agent: JSON-RPC PHP Client <https://github.com/fguillot/JsonRPC>', |
| | 'Content-Type: application/json', |
| | 'Accept: application/json', |
| | 'Connection: close', |
| | ); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | protected $username; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | protected $password; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | protected $debug = false; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | protected $cookies = array(); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | protected $verifySslCertificate = true; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | protected $sslLocalCert; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | protected $beforeRequest; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | public function __construct($url = '') |
| | { |
| | $this->url = $url; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function withUrl($url) |
| | { |
| | $this->url = $url; |
| | return $this; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function withUsername($username) |
| | { |
| | $this->username = $username; |
| | return $this; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function withPassword($password) |
| | { |
| | $this->password = $password; |
| | return $this; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function withTimeout($timeout) |
| | { |
| | $this->timeout = $timeout; |
| | return $this; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function withHeaders(array $headers) |
| | { |
| | $this->headers = array_merge($this->headers, $headers); |
| | return $this; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function withCookies(array $cookies, $replace = false) |
| | { |
| | if ($replace) { |
| | $this->cookies = $cookies; |
| | } else { |
| | $this->cookies = array_merge($this->cookies, $cookies); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | public function withDebug() |
| | { |
| | $this->debug = true; |
| | return $this; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | public function withoutSslVerification() |
| | { |
| | $this->verifySslCertificate = false; |
| | return $this; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | public function withSslLocalCert($path) |
| | { |
| | $this->sslLocalCert = $path; |
| | return $this; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function withBeforeRequestCallback(Closure $closure) |
| | { |
| | $this->beforeRequest = $closure; |
| | return $this; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | public function getCookies() |
| | { |
| | return $this->cookies; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function execute($payload, array $headers = array()) |
| | { |
| | if (is_callable($this->beforeRequest)) { |
| | call_user_func_array($this->beforeRequest, array($this, $payload, $headers)); |
| | } |
| |
|
| | if ($this->isCurlLoaded()) { |
| | $ch = curl_init(); |
| | $requestHeaders = $this->buildHeaders($headers); |
| | $headers = array(); |
| | curl_setopt_array($ch, array( |
| | CURLOPT_URL => trim($this->url), |
| | CURLOPT_RETURNTRANSFER => true, |
| | CURLOPT_CONNECTTIMEOUT => $this->timeout, |
| | CURLOPT_MAXREDIRS => 2, |
| | CURLOPT_SSL_VERIFYPEER => $this->verifySslCertificate, |
| | CURLOPT_POST => true, |
| | CURLOPT_POSTFIELDS => $payload, |
| | CURLOPT_HTTPHEADER => $requestHeaders, |
| | CURLOPT_HEADERFUNCTION => function ($curl, $header) use (&$headers) { |
| | $headers[] = $header; |
| | return strlen($header); |
| | } |
| | )); |
| | if ($this->sslLocalCert !== null) { |
| | curl_setopt($ch, CURLOPT_CAINFO, $this->sslLocalCert); |
| | } |
| | $response = curl_exec($ch); |
| | curl_close($ch); |
| | if ($response !== false) { |
| | $response = json_decode($response, true); |
| | } else { |
| | throw new ConnectionFailureException('Unable to establish a connection'); |
| | } |
| | } else { |
| | $stream = fopen(trim($this->url), 'r', false, $this->buildContext($payload, $headers)); |
| |
|
| | if (! is_resource($stream)) { |
| | throw new ConnectionFailureException('Unable to establish a connection'); |
| | } |
| |
|
| | $metadata = stream_get_meta_data($stream); |
| | $headers = $metadata['wrapper_data']; |
| | $response = json_decode(stream_get_contents($stream), true); |
| |
|
| | fclose($stream); |
| | } |
| |
|
| | if ($this->debug) { |
| | error_log('==> Request: '.PHP_EOL.(is_string($payload) ? $payload : json_encode($payload, JSON_PRETTY_PRINT))); |
| | error_log('==> Headers: '.PHP_EOL.var_export($headers, true)); |
| | error_log('==> Response: '.PHP_EOL.json_encode($response, JSON_PRETTY_PRINT)); |
| | } |
| |
|
| | $this->handleExceptions($headers); |
| | $this->parseCookies($headers); |
| |
|
| | return $response; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | protected function buildContext($payload, array $headers = array()) |
| | { |
| | $headers = $this->buildHeaders($headers); |
| |
|
| | $options = array( |
| | 'http' => array( |
| | 'method' => 'POST', |
| | 'protocol_version' => 1.1, |
| | 'timeout' => $this->timeout, |
| | 'max_redirects' => 2, |
| | 'header' => implode("\r\n", $headers), |
| | 'content' => $payload, |
| | 'ignore_errors' => true, |
| | ), |
| | 'ssl' => array( |
| | 'verify_peer' => $this->verifySslCertificate, |
| | 'verify_peer_name' => $this->verifySslCertificate, |
| | ) |
| | ); |
| |
|
| | if ($this->sslLocalCert !== null) { |
| | $options['ssl']['local_cert'] = $this->sslLocalCert; |
| | } |
| |
|
| | return stream_context_create($options); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | protected function parseCookies(array $headers) |
| | { |
| | foreach ($headers as $header) { |
| | $pos = stripos($header, 'Set-Cookie:'); |
| |
|
| | if ($pos !== false) { |
| | $cookies = explode(';', substr($header, $pos + 11)); |
| |
|
| | foreach ($cookies as $cookie) { |
| | $item = explode('=', $cookie); |
| |
|
| | if (count($item) === 2) { |
| | $name = trim($item[0]); |
| | $value = $item[1]; |
| | $this->cookies[$name] = $value; |
| | } |
| | } |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | public function handleExceptions(array $headers) |
| | { |
| | $exceptions = array( |
| | '401' => '\JsonRPC\Exception\AccessDeniedException', |
| | '403' => '\JsonRPC\Exception\AccessDeniedException', |
| | '404' => '\JsonRPC\Exception\ConnectionFailureException', |
| | '500' => '\JsonRPC\Exception\ServerErrorException', |
| | ); |
| |
|
| | foreach ($headers as $header) { |
| | foreach ($exceptions as $code => $exception) { |
| | if (strpos($header, 'HTTP/1.0 '.$code) !== false || strpos($header, 'HTTP/1.1 '.$code) !== false) { |
| | throw new $exception('Response: '.$header); |
| | } |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | protected function isCurlLoaded() |
| | { |
| | return extension_loaded('curl'); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | protected function buildHeaders(array $headers) |
| | { |
| | $headers = array_merge($this->headers, $headers); |
| |
|
| | if (!empty($this->username) && !empty($this->password)) { |
| | $headers[] = 'Authorization: Basic ' . base64_encode($this->username . ':' . $this->password); |
| | } |
| |
|
| | if (!empty($this->cookies)) { |
| | $cookies = array(); |
| |
|
| | foreach ($this->cookies as $key => $value) { |
| | $cookies[] = $key . '=' . $value; |
| | } |
| |
|
| | $headers[] = 'Cookie: ' . implode('; ', $cookies); |
| | } |
| | return $headers; |
| | } |
| | } |
| |
|