Completed
Pull Request — master (#110)
by Ruben de
72:04
created

RestClient::request()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 7
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Blocktrail\SDK\Connection;
4
5
use Blocktrail\SDK\Blocktrail;
6
use GuzzleHttp\Client as Guzzle;
7
use GuzzleHttp\Handler\CurlHandler;
8
use GuzzleHttp\HandlerStack;
9
use HttpSignatures\Context;
10
use HttpSignatures\GuzzleHttpSignatures;
11
12
class RestClient extends BaseRestClient
13
{
14
    /**
15
     * @var array
16
     */
17
    protected $options = [];
18
19
    /**
20
     * @var array
21
     */
22
    protected $curlOptions = [];
23
24
    /**
25
     * @var Guzzle
26
     */
27
    protected $guzzle;
28
29
    /**
30
     * GuzzleRestClient constructor.
31
     * @param $apiEndpoint
32
     * @param $apiVersion
33
     * @param $apiKey
34
     * @param $apiSecret
35
     */
36 118
    public function __construct($apiEndpoint, $apiVersion, $apiKey, $apiSecret) {
37 118
        parent::__construct($apiEndpoint, $apiVersion, $apiKey, $apiSecret);
38 118
        $this->guzzle = $this->createGuzzleClient();
39 118
    }
40
41
    /**
42
     * @param array $options
43
     * @param array $curlOptions
44
     * @return Guzzle
45
     */
46 118
    protected function createGuzzleClient(array $options = [], array $curlOptions = []) {
47 118
        $options = $options + $this->options;
48 118
        $curlOptions = $curlOptions + $this->curlOptions;
49
50 118
        $context = new Context([
0 ignored issues
show
Unused Code introduced by
$context is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
51 118
            'keys' => [$this->apiKey => $this->apiSecret],
52 118
            'algorithm' => 'hmac-sha256',
53
            'headers' => ['(request-target)', 'Content-MD5', 'Date'],
54
        ]);
55
56 118
        $curlHandler = new CurlHandler($curlOptions);
57 118
        $handler = HandlerStack::create($curlHandler);
58 118
//        $handler->push(GuzzleHttpSignatures::middlewareFromContext($context));
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
59
60 118
        return new Guzzle($options + array(
61 118
            'handler' => $handler,
62 118
            'base_uri' => $this->apiEndpoint,
63
            'headers' => array(
64
                'User-Agent' => Blocktrail::SDK_USER_AGENT . '/' . Blocktrail::SDK_VERSION,
65
            ),
66
            'http_errors' => false,
67 118
            'connect_timeout' => 3,
68 118
            'timeout' => 20.0, // tmp until we have a good matrix of all the requests and their expect min/max time
69
            'verify' => true,
70 118
            'proxy' => '',
71
            'debug' => false,
72
            'config' => array(),
73 118
            'auth' => '',
74
        ));
75
    }
76
77
    /**
78
     * @return Guzzle
79
     */
80
    public function getGuzzleClient() {
81
        return $this->guzzle;
82
    }
83
84
    /**
85
     * enable CURL debugging output
86
     *
87
     * @param   bool        $debug
88
     */
89
    public function setCurlDebugging($debug = true) {
90
        $this->options['debug'] = $debug;
91
92
        $this->guzzle = $this->createGuzzleClient();
93
    }
94
95
96
    /**
97
     * set cURL default option on Guzzle client
98
     * @param string    $key
99
     * @param bool      $value
100
     */
101
    public function setCurlDefaultOption($key, $value) {
102
        $this->curlOptions[$key] = $value;
103
104
        $this->guzzle = $this->createGuzzleClient();
105
    }
106
107
    /**
108
     * set the proxy config for Guzzle
109
     *
110
     * @param   $proxy
111
     */
112
    public function setProxy($proxy) {
113
        $this->options['proxy'] = $proxy;
114
115
        $this->guzzle = $this->createGuzzleClient();
116
    }
117
118
    /**
119
     * generic request executor
120
     *
121
     * @param   string          $method         GET, POST, PUT, DELETE
122
     * @param   string          $endpointUrl
123
     * @param   array           $queryString
124
     * @param   array|string    $body
125
     * @param   string          $auth           http-signatures to enable http-signature signing
126
     * @param   string          $contentMD5Mode body or url
127
     * @param   float           $timeout        timeout in seconds
128
     * @return Response
129
     */
130 33
    public function request($method, $endpointUrl, $queryString = null, $body = null, $auth = null, $contentMD5Mode = null, $timeout = null) {
131 33
        $request = $this->buildRequest($method, $endpointUrl, $queryString, $body, $auth, $contentMD5Mode, $timeout);
132 33
        $response = $this->guzzle->send($request, ['auth' => $auth, 'timeout' => $timeout]);
133
134 33
        return $this->responseHandler($response);
0 ignored issues
show
Documentation introduced by
$response is of type object<Psr\Http\Message\ResponseInterface>, but the function expects a object<Blocktrail\SDK\Co...tion\ResponseInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
135
    }
136
137
    public function responseHandler(ResponseInterface $responseObj) {
138
        $httpResponseCode = (int)$responseObj->getStatusCode();
139
        $httpResponsePhrase = (string)$responseObj->getReasonPhrase();
140
        $body = $responseObj->getBody();
141
142
        sleep(1);
143
144
        if ($httpResponseCode == 200) {
145
            if (!$body) {
146
                throw new EmptyResponse(Blocktrail::EXCEPTION_EMPTY_RESPONSE, $httpResponseCode);
147
            }
148
149
            $result = new Response($httpResponseCode, $body);
150
151
            return $result;
152
        } elseif ($httpResponseCode == 400 || $httpResponseCode == 403) {
153
            $data = json_decode($body, true);
154
155
            if ($data && isset($data['msg'], $data['code'])) {
156
                throw new EndpointSpecificError(!is_string($data['msg']) ? json_encode($data['msg']) : $data['msg'], $data['code']);
157
            } else {
158
                if (preg_match("/^banned( IP)? \[(.+)\]\n?$/", $body, $m)) {
159
                    throw new BannedIP($m[2]);
160
                }
161
162
                throw new UnknownEndpointSpecificError($this->verboseErrors ? $body : Blocktrail::EXCEPTION_UNKNOWN_ENDPOINT_SPECIFIC_ERROR);
163
            }
164
        } elseif ($httpResponseCode == 401) {
165
            throw new InvalidCredentials($this->verboseErrors ? $body : Blocktrail::EXCEPTION_INVALID_CREDENTIALS, $httpResponseCode);
166
        } elseif ($httpResponseCode == 404) {
167
            if ($httpResponsePhrase == "Endpoint Not Found") {
168
                throw new MissingEndpoint($this->verboseErrors ? $body : Blocktrail::EXCEPTION_MISSING_ENDPOINT, $httpResponseCode);
169
            } else {
170
                throw new ObjectNotFound($this->verboseErrors ? $body : Blocktrail::EXCEPTION_OBJECT_NOT_FOUND, $httpResponseCode);
171
            }
172
        } elseif ($httpResponseCode == 500) {
173
            throw new GenericServerError(Blocktrail::EXCEPTION_GENERIC_SERVER_ERROR . "\nServer Response: " . $body, $httpResponseCode);
174
        } else {
175
            throw new GenericHTTPError(Blocktrail::EXCEPTION_GENERIC_HTTP_ERROR . "\nServer Response: " . $body, $httpResponseCode);
176
        }
177
    }
178
179
    /**
180
     * Returns curent fate time in RFC1123 format, using UTC time zone
181
     *
182
     * @return  string
183
     */
184
    private function getRFC1123DateString() {
0 ignored issues
show
Bug introduced by
Consider using a different method name as you override a private method of the parent class.

Overwriting private methods is generally fine as long as you also use private visibility. It might still be preferable for understandability to use a different method name.

Loading history...
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
185
        $date = new \DateTime(null, new \DateTimeZone("UTC"));
186
        return str_replace("+0000", "GMT", $date->format(\DateTime::RFC1123));
187
    }
188
}
189