Completed
Push — master ( b56b73...859bb4 )
by Carlos
03:56 queued 01:23
created

Http::getMiddlewares()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
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
/**
13
 * Http.php.
14
 *
15
 * This file is part of the wechat-components.
16
 *
17
 * (c) overtrue <[email protected]>
18
 *
19
 * This source file is subject to the MIT license that is bundled
20
 * with this source code in the file LICENSE.
21
 */
22
23
namespace EasyWeChat\Core;
24
25
use EasyWeChat\Core\Exceptions\HttpException;
26
use EasyWeChat\Support\Log;
27
use GuzzleHttp\Client as HttpClient;
28
use GuzzleHttp\HandlerStack;
29
use Psr\Http\Message\ResponseInterface;
30
31
/**
32
 * Class Http.
33
 */
34
class Http
35
{
36
    /**
37
     * Http client.
38
     *
39
     * @var HttpClient
40
     */
41
    protected $client;
42
43
    /**
44
     * The middlewares.
45
     *
46
     * @var array
47
     */
48
    protected $middlewares = [];
49
50
    /**
51
     * Guzzle client default settings.
52
     *
53
     * @var array
54
     */
55
    protected static $defaults = [];
56
57
    /**
58
     * Set guzzle default settings.
59
     *
60
     * @param array $defaults
61
     */
62 6
    public static function setDefaultOptions($defaults = [])
63
    {
64 5
        self::$defaults = $defaults;
65 6
    }
66
67
    /**
68
     * Return current guzzle default settings.
69
     *
70
     * @return array
71
     */
72 1
    public static function getDefaultOptions()
73
    {
74 1
        return self::$defaults;
75
    }
76
77
    /**
78
     * GET request.
79
     *
80
     * @param string $url
81
     * @param array  $options
82
     *
83
     * @return ResponseInterface
84
     *
85
     * @throws HttpException
86
     */
87 1
    public function get($url, array $options = [])
88
    {
89 1
        return $this->request($url, 'GET', ['query' => $options]);
90
    }
91
92
    /**
93
     * POST request.
94
     *
95
     * @param string       $url
96
     * @param array|string $options
97
     *
98
     * @return ResponseInterface
99
     *
100
     * @throws HttpException
101
     */
102 1
    public function post($url, $options = [])
103
    {
104 1
        $key = is_array($options) ? 'form_params' : 'body';
105
106 1
        return $this->request($url, 'POST', [$key => $options]);
107
    }
108
109
     /**
110
      * JSON request.
111
      *
112
      * @param string       $url
113
      * @param string|array $options
114
      * @param array $queries
115
      * @param int          $encodeOption
116
      *
117
      * @return ResponseInterface
118
      *
119
      * @throws HttpException
120
      */
121 1
     public function json($url, $options = [], $encodeOption = JSON_UNESCAPED_UNICODE, $queries = [])
122
     {
123 1
         is_array($options) && $options = json_encode($options, $encodeOption);
124
125 1
         return $this->request($url, 'POST', ['query' => $queries, 'body' => $options, 'headers' => ['content-type' => 'application/json']]);
126
     }
127
128
    /**
129
     * Upload file.
130
     *
131
     * @param string $url
132
     * @param array  $files
133
     * @param array  $form
134
     *
135
     * @return ResponseInterface
136
     *
137
     * @throws HttpException
138
     */
139 1
    public function upload($url, array $files = [], array $form = [], array $queries = [])
140
    {
141 1
        $multipart = [];
142
143 1
        foreach ($files as $name => $path) {
144 1
            $multipart[] = [
145 1
                'name' => $name,
146 1
                'contents' => fopen($path, 'r'),
147
            ];
148 1
        }
149
150 1
        foreach ($form as $name => $contents) {
151 1
            $multipart[] = compact('name', 'contents');
152 1
        }
153
154 1
        return $this->request($url, 'POST', ['query' => $queries, 'multipart' => $multipart]);
155
    }
156
157
    /**
158
     * Set GuzzleHttp\Client.
159
     *
160
     * @param \GuzzleHttp\Client $client
161
     *
162
     * @return Http
163
     */
164 6
    public function setClient(HttpClient $client)
165
    {
166 6
        $this->client = $client;
167
168 6
        return $this;
169
    }
170
171
    /**
172
     * Return GuzzleHttp\Client instance.
173
     *
174
     * @return \GuzzleHttp\Client
175
     */
176 3
    public function getClient()
177
    {
178 3
        if (!($this->client instanceof HttpClient)) {
179 1
            $this->client = new HttpClient();
180 1
        }
181
182 3
        return $this->client;
183
    }
184
185
    /**
186
     * Add a middleware.
187
     *
188
     * @param callable $middleware
189
     *
190
     * @return $this
191
     */
192 8
    public function addMiddleware(callable $middleware)
193
    {
194 8
        array_push($this->middlewares, $middleware);
195
196 8
        return $this;
197
    }
198
199
    /**
200
     * Return all middlewares.
201
     *
202
     * @return array
203
     */
204 8
    public function getMiddlewares()
205
    {
206 8
        return $this->middlewares;
207
    }
208
209
    /**
210
     * Make a request.
211
     *
212
     * @param string $url
213
     * @param string $method
214
     * @param array  $options
215
     *
216
     * @return ResponseInterface
217
     *
218
     * @throws HttpException
219
     */
220 2
    public function request($url, $method = 'GET', $options = [])
221
    {
222 2
        $method = strtoupper($method);
223
224 2
        $options = array_merge(self::$defaults, $options);
225
226 2
        Log::debug('Client Request:', compact('url', 'method', 'options'));
227
228 2
        $options['handler'] = $this->getHandler();
229
230 2
        $response = $this->getClient()->request($method, $url, $options);
231
232 2
        Log::debug('API response:', [
233 2
            'Status' => $response->getStatusCode(),
234 2
            'Reason' => $response->getReasonPhrase(),
235 2
            'Headers' => $response->getHeaders(),
236 2
            'Body' => strval($response->getBody()),
237 2
        ]);
238
239 2
        return $response;
240
    }
241
242
    /**
243
     * @param \Psr\Http\Message\ResponseInterface|string $body
244
     *
245
     * @return mixed
246
     *
247
     * @throws \EasyWeChat\Core\Exceptions\HttpException
248
     */
249 10
    public function parseJSON($body)
250
    {
251 10
        if ($body instanceof ResponseInterface) {
252 2
            $body = $body->getBody();
253 2
        }
254
255
        // XXX: json maybe contains special chars. So, let's FUCK the WeChat API developers ...
256 10
        $body = $this->fuckTheWeChatInvalidJSON($body);
257
258 10
        if (empty($body)) {
259 1
            return false;
260
        }
261
262 10
        $contents = json_decode($body, true);
263
264 10
        Log::debug('API response decoded:', compact('contents'));
265
266 10
        if (JSON_ERROR_NONE !== json_last_error()) {
267 1
            throw new HttpException('Failed to parse JSON: '.json_last_error_msg());
268
        }
269
270 10
        return $contents;
271
    }
272
273
    /**
274
     * Filter the invalid JSON string.
275
     *
276
     * @param \Psr\Http\Message\StreamInterface|string $invalidJSON
277
     *
278
     * @return string
279
     */
280 10
    protected function fuckTheWeChatInvalidJSON($invalidJSON)
281
    {
282 10
        return preg_replace('/[\x00-\x1F\x80-\x9F]/u', '', trim($invalidJSON));
283
    }
284
285
    /**
286
     * Build a handler.
287
     *
288
     * @return HandlerStack
289
     */
290 2
    protected function getHandler()
291
    {
292 2
        $stack = HandlerStack::create();
293
294 2
        foreach ($this->middlewares as $middleware) {
295
            $stack->push($middleware);
296 2
        }
297
298 2
        return $stack;
299
    }
300
}
301