Passed
Push — master ( e2096a...4ef8f1 )
by frey
04:20 queued 01:49
created

BaseClient::httpPutJson()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 3
1
<?php
2
3
namespace Freyo\ApiGateway\Kernel;
4
5
use Freyo\ApiGateway\Kernel\Http\Response;
6
use Freyo\ApiGateway\Kernel\Traits\HasHttpRequests;
7
use Freyo\ApiGateway\Kernel\Traits\WithFingerprint;
8
use GuzzleHttp\MessageFormatter;
9
use GuzzleHttp\Middleware;
10
use Psr\Http\Message\RequestInterface;
11
use Psr\Http\Message\ResponseInterface;
12
use function Freyo\ApiGateway\Kernel\Support\generate_sign;
13
14
class BaseClient
15
{
16
    use WithFingerprint, HasHttpRequests {
17
        request as performRequest;
18
    }
19
20
    /**
21
     * @var \Freyo\ApiGateway\Kernel\ServiceContainer
22
     */
23
    protected $app;
24
25
    /**
26
     * @var string
27
     */
28
    protected $baseUri;
29
30
    /**
31
     * BaseClient constructor.
32
     *
33
     * @param \Freyo\ApiGateway\Kernel\ServiceContainer $app
34
     */
35
    public function __construct(ServiceContainer $app)
36
    {
37
        $this->app     = $app;
38
        $this->baseUri = $this->getBaseUri();
39
40
        $this->setHttpClient($this->app['http_client']);
41
    }
42
43
    /**
44
     * GET request.
45
     *
46
     * @param string $url
47
     * @param array $query
48
     *
49
     * @return \Psr\Http\Message\ResponseInterface|\Freyo\ApiGateway\Kernel\Support\Collection|array|object|string
50
     *
51
     * @throws \Freyo\ApiGateway\Kernel\Exceptions\InvalidConfigException
52
     */
53
    public function httpGet($url, array $query = [])
54
    {
55
        return $this->request($url, 'GET', ['query' => $query]);
56
    }
57
58
    /**
59
     * POST request.
60
     *
61
     * @param string $url
62
     * @param array $data
63
     *
64
     * @return \Psr\Http\Message\ResponseInterface|\Freyo\ApiGateway\Kernel\Support\Collection|array|object|string
65
     *
66
     * @throws \Freyo\ApiGateway\Kernel\Exceptions\InvalidConfigException
67
     */
68
    public function httpPost($url, array $data = [])
69
    {
70
        return $this->request($url, 'POST', ['form_params' => $data]);
71
    }
72
73
    /**
74
     * PUT request.
75
     *
76
     * @param string $url
77
     * @param array $data
78
     *
79
     * @return \Psr\Http\Message\ResponseInterface|\Freyo\ApiGateway\Kernel\Support\Collection|array|object|string
80
     *
81
     * @throws \Freyo\ApiGateway\Kernel\Exceptions\InvalidConfigException
82
     */
83
    public function httpPut($url, array $data = [])
84
    {
85
        return $this->request($url, 'PUT', ['form_params' => $data]);
86
    }
87
88
    /**
89
     * JSON request.
90
     *
91
     * @param string $url
92
     * @param string|array $data
93
     * @param array $query
94
     *
95
     * @return \Psr\Http\Message\ResponseInterface|\Freyo\ApiGateway\Kernel\Support\Collection|array|object|string
96
     *
97
     * @throws \Freyo\ApiGateway\Kernel\Exceptions\InvalidConfigException
98
     */
99
    public function httpPostJson($url, array $data = [], array $query = [])
100
    {
101
        return $this->request($url, 'POST', ['query' => $query, 'json' => $data]);
102
    }
103
104
    /**
105
     * JSON request.
106
     *
107
     * @param string $url
108
     * @param string|array $data
109
     * @param array $query
110
     *
111
     * @return \Psr\Http\Message\ResponseInterface|\Freyo\ApiGateway\Kernel\Support\Collection|array|object|string
112
     *
113
     * @throws \Freyo\ApiGateway\Kernel\Exceptions\InvalidConfigException
114
     */
115
    public function httpPutJson($url, array $data = [], array $query = [])
116
    {
117
        return $this->request($url, 'PUT', ['query' => $query, 'json' => $data]);
118
    }
119
120
    /**
121
     * Upload file.
122
     *
123
     * @param string $url
124
     * @param array $files
125
     * @param array $form
126
     * @param array $query
127
     *
128
     * @return \Psr\Http\Message\ResponseInterface|\Freyo\ApiGateway\Kernel\Support\Collection|array|object|string
129
     *
130
     * @throws \Freyo\ApiGateway\Kernel\Exceptions\InvalidConfigException
131
     */
132
    public function httpUpload($url, array $files = [], array $form = [], array $query = [])
133
    {
134
        $multipart = [];
135
136
        foreach ($files as $name => $path) {
137
            $multipart[] = [
138
                'name' => $name,
139
                'contents' => fopen($path, 'r'),
140
            ];
141
        }
142
143
        foreach ($form as $name => $contents) {
144
            $multipart[] = compact('name', 'contents');
145
        }
146
147
        return $this->request($url, 'POST', [
148
            'query' => $query,
149
            'multipart' => $multipart,
150
            'connect_timeout' => 30,
151
            'timeout' => 30,
152
            'read_timeout' => 30
153
        ]);
154
    }
155
156
    /**
157
     * Make a request and return raw response.
158
     *
159
     * @param string $url
160
     * @param string $method
161
     * @param array $options
162
     *
163
     * @return ResponseInterface
164
     *
165
     * @throws \Freyo\ApiGateway\Kernel\Exceptions\InvalidConfigException
166
     */
167
    public function requestRaw($url, $method = 'GET', array $options = [])
168
    {
169
        return Response::buildFromPsrResponse($this->request($url, $method, $options, true));
170
    }
171
172
    /**
173
     * Make a API request.
174
     *
175
     * @param string $url
176
     * @param string $method
177
     * @param array $options
178
     * @param bool $returnRaw
179
     *
180
     * @return \Psr\Http\Message\ResponseInterface|\Freyo\ApiGateway\Kernel\Support\Collection|array|object|string
181
     *
182
     * @throws \Freyo\ApiGateway\Kernel\Exceptions\InvalidConfigException
183
     */
184
    public function request($url, $method = 'GET', array $options = [], $returnRaw = false)
185
    {
186
        if (empty($this->middlewares)) {
187
            $this->registerHttpMiddlewares();
188
        }
189
190
        $headers = array_merge(
191
            ['Date' => gmdate("D, d M Y H:i:s T"), 'Source' => $this->app->getSource()],
192
            $options['headers'] ?? []
193
        );
194
195
        if ($this->app->withFingerprint()) {
196
            $headers['Fingerprint'] = $this->fingerprint(
197
                $method,
198
                $this->baseUri . $url,
199
                ($options['json'] ?? []) + ($options['form_params'] ?? []) + ($options['query'] ?? [])
200
            );
201
        }
202
203
        if ($this->app->needAuth()) {
204
            $headers['Authorization'] = $this->authorization($headers);
205
        }
206
207
        $options = array_merge($options, ['headers' => $headers]);
208
209
        $response = $this->performRequest($url, $method, $options);
0 ignored issues
show
Bug introduced by
The method performRequest() does not exist on Freyo\ApiGateway\Kernel\BaseClient. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

209
        /** @scrutinizer ignore-call */ 
210
        $response = $this->performRequest($url, $method, $options);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
210
211
        return $returnRaw ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
0 ignored issues
show
Bug Best Practice introduced by
The property config does not exist on Freyo\ApiGateway\Kernel\ServiceContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
212
    }
213
214
    /**
215
     * Register Guzzle middlewares.
216
     */
217
    protected function registerHttpMiddlewares()
218
    {
219
        // jaeger
220
        if ($this->app['config']->has('jaeger')) {
221
            $this->pushMiddleware($this->jaegerMiddleware(), 'jaeger');
222
        }
223
224
        // tap
225
        if ($this->app['config']->has('tap')) {
226
            $this->pushMiddleware($this->tapMiddleware(), 'tap');
227
        }
228
229
        // log
230
        $this->pushMiddleware($this->logMiddleware(), 'log');
231
    }
232
233
    /**
234
     * Log the request.
235
     *
236
     * @return \Closure
237
     */
238
    protected function logMiddleware()
239
    {
240
        $formatter = new MessageFormatter($this->app['config']->get('http.log_template', MessageFormatter::DEBUG));
241
242
        return Middleware::log($this->app['logger'], $formatter);
243
    }
244
245
    /**
246
     * Jaeger.
247
     *
248
     * @return \Closure
249
     */
250
    protected function jaegerMiddleware()
251
    {
252
        return Middleware::mapRequest(function (RequestInterface $request) {
253
254
            if ($headers = $this->app['config']->get('jaeger.headers', [])) {
255
256
                $headers = is_callable($headers) ? call_user_func($headers, $request) : $headers;
257
258
                foreach ($headers as $name => $value) {
259
                    $request = $request->withHeader($name, $value);
260
                }
261
            }
262
263
            return $request;
264
        });
265
    }
266
267
    /**
268
     * Middleware that invokes a callback before and after sending a request.
269
     *
270
     * @return \Closure
271
     */
272
    protected function tapMiddleware()
273
    {
274
        return Middleware::tap(
275
            is_callable($before = $this->app['config']->get('tap.before')) ? $before : null,
276
            is_callable($after = $this->app['config']->get('tap.after')) ? $after : null
277
        );
278
    }
279
280
    /**
281
     * Extra request params.
282
     *
283
     * @return array
284
     */
285
    protected function prepends()
286
    {
287
        return [];
288
    }
289
290
    /**
291
     * @return string
292
     */
293
    protected function getBaseUri()
294
    {
295
        return $this->app['config']->get('http.base_uri');
296
    }
297
298
    /**
299
     * Wrapping an API endpoint.
300
     *
301
     * @param string $endpoint
302
     * @param string $prefix
303
     *
304
     * @return string
305
     */
306
    protected function wrap($endpoint, $prefix = '')
307
    {
308
        return implode('/', [$prefix, $endpoint]);
309
    }
310
311
    /**
312
     * @param array $headers
313
     *
314
     * @return string
315
     */
316
    protected function authorization(array $headers)
317
    {
318
        $signature = generate_sign($headers, $this->app->getSecretKey());
319
320
        $authorization = sprintf(
321
            'hmac id="%s", algorithm="hmac-sha1", headers="%s", signature="%s"',
322
            $this->app->getSecretId(),
323
            implode(' ', array_map('strtolower', array_keys($headers))),
324
            $signature
325
        );
326
327
        return $authorization;
328
    }
329
}
330