Test Failed
Pull Request — master (#1455)
by
unknown
03:43
created

BaseClient::getHttpClient()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the overtrue/wechat.
5
 *
6
 * (c) overtrue <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace EasyWeChat\Kernel;
13
14
use EasyWeChat\Kernel\Contracts\AccessTokenInterface;
15
use EasyWeChat\Kernel\Http\Response;
16
use EasyWeChat\Kernel\Traits\HasHttpRequests;
17
use GuzzleHttp\Client;
18
use GuzzleHttp\ClientInterface;
19
use GuzzleHttp\MessageFormatter;
20
use GuzzleHttp\Middleware;
21
use Psr\Http\Message\RequestInterface;
22
use Psr\Http\Message\ResponseInterface;
23
24
/**
25
 * Class BaseClient.
26
 *
27
 * @author overtrue <[email protected]>
28
 */
29
class BaseClient
30
{
31
    use HasHttpRequests { request as performRequest; }
32
33
    /**
34
     * @var \EasyWeChat\Kernel\ServiceContainer
35
     */
36
    protected $app;
37
38
    /**
39
     * @var \EasyWeChat\Kernel\Contracts\AccessTokenInterface
40
     */
41
    protected $accessToken;
42
43
    /**
44
     * @var
45
     */
46
    protected $baseUri;
47
48
    /**
49
     * BaseClient constructor.
50
     *
51
     * @param \EasyWeChat\Kernel\ServiceContainer                    $app
52
     * @param \EasyWeChat\Kernel\Contracts\AccessTokenInterface|null $accessToken
53
     */
54 437
    public function __construct(ServiceContainer $app, AccessTokenInterface $accessToken = null)
55
    {
56 437
        $this->app = $app;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 9 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
57 437
        $this->accessToken = $accessToken ?? $this->app['access_token'];
58 437
    }
59
60
    /**
61
     * GET request.
62
     *
63
     * @param string $url
64
     * @param array  $query
65
     *
66
     * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
67
     *
68
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
69
     */
70 1
    public function httpGet(string $url, array $query = [])
71
    {
72 1
        return $this->request($url, 'GET', ['query' => $query]);
73
    }
74
75
    /**
76
     * POST request.
77
     *
78
     * @param string $url
79
     * @param array  $data
80
     *
81
     * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
82
     *
83
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
84
     */
85 1
    public function httpPost(string $url, array $data = [])
86
    {
87 1
        return $this->request($url, 'POST', ['form_params' => $data]);
88
    }
89
90
    /**
91
     * JSON request.
92
     *
93
     * @param string       $url
94
     * @param string|array $data
95
     * @param array        $query
96
     *
97
     * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
98
     *
99
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
100
     */
101 1
    public function httpPostJson(string $url, array $data = [], array $query = [])
102
    {
103 1
        return $this->request($url, 'POST', ['query' => $query, 'json' => $data]);
104
    }
105
106
    /**
107
     * Upload file.
108
     *
109
     * @param string $url
110
     * @param array  $files
111
     * @param array  $form
112
     * @param array  $query
113
     *
114
     * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
115
     *
116
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
117
     */
118 1
    public function httpUpload(string $url, array $files = [], array $form = [], array $query = [])
119
    {
120 1
        $multipart = [];
121
122 1
        foreach ($files as $name => $path) {
123 1
            $multipart[] = [
124 1
                'name' => $name,
125 1
                'contents' => fopen($path, 'r'),
126
            ];
127
        }
128
129 1
        foreach ($form as $name => $contents) {
130 1
            $multipart[] = compact('name', 'contents');
131
        }
132
133 1
        return $this->request($url, 'POST', ['query' => $query, 'multipart' => $multipart, 'connect_timeout' => 30, 'timeout' => 30, 'read_timeout' => 30]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 140 characters; contains 156 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
134
    }
135
136
    /**
137
     * @return AccessTokenInterface
138
     */
139 1
    public function getAccessToken(): AccessTokenInterface
140
    {
141 1
        return $this->accessToken;
142
    }
143
144
    /**
145
     * @param \EasyWeChat\Kernel\Contracts\AccessTokenInterface $accessToken
146
     *
147
     * @return $this
148
     */
149 1
    public function setAccessToken(AccessTokenInterface $accessToken)
150
    {
151 1
        $this->accessToken = $accessToken;
152
153 1
        return $this;
154
    }
155
156
    /**
157
     * @param string $url
158
     * @param string $method
159
     * @param array  $options
160
     * @param bool   $returnRaw
161
     *
162
     * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
163
     *
164
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
165
     */
166 1
    public function request(string $url, string $method = 'GET', array $options = [], $returnRaw = false)
167
    {
168 1
        if (empty($this->middlewares)) {
169 1
            $this->registerHttpMiddlewares();
170
        }
171
172 1
        $response = $this->performRequest($url, $method, $options);
173
174 1
        return $returnRaw ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
175
    }
176
177
    /**
178
     * @param string $url
179
     * @param string $method
180
     * @param array  $options
181
     *
182
     * @return \EasyWeChat\Kernel\Http\Response
183
     *
184
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
185
     */
186 1
    public function requestRaw(string $url, string $method = 'GET', array $options = [])
187
    {
188 1
        return Response::buildFromPsrResponse($this->request($url, $method, $options, true));
189
    }
190
191
    /**
192
     * Register Guzzle middlewares.
193
     */
194
    protected function registerHttpMiddlewares()
195
    {
196 1
        // retry
197
        $this->pushMiddleware($this->retryMiddleware(), 'retry');
198 1
        // access token
199 1
        $this->pushMiddleware($this->accessTokenMiddleware(), 'access_token');
200
        // log
201
        $this->pushMiddleware($this->logMiddleware(), 'log');
202 1
    }
203
204
    /**
205
     * Attache access token to request query.
206
     *
207
     * @return \Closure
208 1
     */
209
    protected function accessTokenMiddleware()
210
    {
211 1
        return function (callable $handler) {
212
            return function (RequestInterface $request, array $options) use ($handler) {
213 1
                if ($this->accessToken) {
214
                    $request = $this->accessToken->applyToRequest($request, $options);
215 1
                }
216 1
217
                return $handler($request, $options);
218
            };
219
        };
220
    }
221
222
    /**
223
     * Log the request.
224
     *
225
     * @return \Closure
226 1
     */
227 1
    protected function logMiddleware()
228 1
    {
229
        $formatter = new MessageFormatter($this->app['config']['http.log_template'] ?? MessageFormatter::DEBUG);
230
231 1
        return Middleware::log($this->app['logger'], $formatter);
232 1
    }
233 1
234
    /**
235
     * Return retry middleware.
236
     *
237
     * @return \Closure
238
     */
239
    protected function retryMiddleware()
240
    {
241 1
        return Middleware::retry(function (
242
            $retries,
243 1
            RequestInterface $request,
244
            ResponseInterface $response = null
245 1
        ) {
246
            // Limit the number of retries to 2
247
            if ($retries < $this->app->config->get('http.max_retries', 1) && $response && $body = $response->getBody()) {
248
                // Retry on server errors
249
                $response = json_decode($body, true);
250
251
                if (!empty($response['errcode']) && in_array(abs($response['errcode']), [40001, 40014, 42001], true)) {
252
                    $this->accessToken->refresh();
253
                    $this->app['logger']->debug('Retrying with refreshed access token.');
254
255 1
                    return true;
256
                }
257
            }
258
259
            return false;
260
        }, function () {
261 1
            return abs($this->app->config->get('http.retry_delay', 500));
262
        });
263 1
    }
264
}
265