LaraClient::logRequest()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
eloc 9
c 1
b 0
f 1
nc 4
nop 4
dl 0
loc 12
rs 9.9666
1
<?php
2
3
namespace Usamamuneerchaudhary\LaraClient;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Exception\GuzzleException;
7
use GuzzleHttp\Exception\RequestException;
8
use Illuminate\Support\Facades\Cache;
9
use Illuminate\Support\Facades\Config;
10
use Psr\Http\Message\ResponseInterface;
11
use Usamamuneerchaudhary\LaraClient\Contracts\LaraClientInterface;
12
use Usamamuneerchaudhary\LaraClient\Exceptions\LaraClientApiClientException;
13
use Usamamuneerchaudhary\LaraClient\Models\LaraClientLog;
14
15
class LaraClient implements LaraClientInterface
16
{
17
    protected $httpClient;
18
    protected $config;
19
20
    /**
21
     * @param $connection
22
     */
23
    public function __construct($connection = null)
24
    {
25
        $this->config = Config::get('lara_client.connections.'.($connection ?: Config::get('lara_client.default')));
26
        $this->httpClient = new Client([
27
            'base_uri' => $this->config['base_uri'],
28
            'headers' => $this->config['default_headers'],
29
            'timeout' => $this->config['timeout'],
30
        ]);
31
    }
32
33
    /**
34
     * @param $uri
35
     * @param $queryParams
36
     * @return Response
37
     * @throws GuzzleException
38
     * @throws LaraClientApiClientException
39
     */
40
    public function get($uri, $queryParams = []): Response
41
    {
42
        $fullUrl = $this->getFullUrl($uri);
43
        return $this->request('GET', $fullUrl, ['query' => $queryParams]);
44
    }
45
46
    /**
47
     * @param $uri
48
     * @param $data
49
     * @return Response
50
     * @throws GuzzleException
51
     * @throws LaraClientApiClientException
52
     */
53
    public function post($uri, $data = []): Response
54
    {
55
        $fullUrl = $this->getFullUrl($uri);
56
        return $this->request('POST', $fullUrl, ['json' => $data]);
57
    }
58
59
    /**
60
     * @param $uri
61
     * @param $data
62
     * @return Response
63
     * @throws GuzzleException
64
     * @throws LaraClientApiClientException
65
     */
66
    public function put($uri, $data = []): Response
67
    {
68
        $fullUrl = $this->getFullUrl($uri);
69
        return $this->request('PUT', $fullUrl, ['json' => $data]);
70
    }
71
72
    /**
73
     * @param $uri
74
     * @param $data
75
     * @return Response
76
     * @throws GuzzleException
77
     * @throws LaraClientApiClientException
78
     */
79
    public function patch($uri, $data = []): Response
80
    {
81
        $fullUrl = $this->getFullUrl($uri);
82
        return $this->request('PATCH', $fullUrl, ['json' => $data]);
83
    }
84
85
    /**
86
     * @param $uri
87
     * @param $data
88
     * @return Response
89
     * @throws GuzzleException
90
     * @throws LaraClientApiClientException
91
     */
92
    public function delete($uri, $data = []): Response
93
    {
94
        $fullUrl = $this->getFullUrl($uri);
95
        return $this->request('DELETE', $fullUrl, ['json' => $data]);
96
    }
97
98
    /**
99
     * @throws LaraClientApiClientException
100
     * @throws GuzzleException
101
     */
102
    protected function request($method, $uri, $options): Response
103
    {
104
        $options['headers'] = $this->getHeaders();
105
106
        if (Cache::has('api_rate_limit')) {
107
            sleep($this->config['rate_limit']['interval']);
108
        }
109
110
        try {
111
            $response = $this->httpClient->request($method, $uri, $options);
112
            $this->logRequest($method, $uri, $options, $response);
113
            $this->handleRateLimit($response->getHeader('X-RateLimit-Reset'));
114
        } catch (RequestException $e) {
115
            $response = $e->getResponse();
116
117
            if ($response->getStatusCode() === 429) {
118
                $this->handleRateLimit($response->getHeader('X-RateLimit-Reset'));
119
                return $this->request($method, $uri, $options);
120
            }
121
            throw new LaraClientApiClientException($response->getStatusCode(), $response->getReasonPhrase());
122
        }
123
        return new Response($response->getStatusCode(), $response->getBody());
124
    }
125
126
    /**
127
     * @param $additionalHeaders
128
     * @return array
129
     */
130
    protected function getHeaders($additionalHeaders = []): array
131
    {
132
        // Merge the default headers with any additional headers passed in
133
        $headers = array_merge($this->config['default_headers'], $additionalHeaders);
134
135
        // Add the Authorization header if an API key is set
136
        if (!empty($this->config['api_key'])) {
137
            $headers['Authorization'] = 'Bearer '.$this->config['api_key'];
138
        }
139
140
        return $headers;
141
    }
142
143
    /**
144
     * @param $resetHeader
145
     * @return void
146
     */
147
    protected function handleRateLimit($resetHeader): void
148
    {
149
        if (!empty($resetHeader)) {
150
            $resetTimestamp = (int) $resetHeader[0];
151
            $currentTimestamp = time();
152
153
            if ($resetTimestamp > $currentTimestamp) {
154
                $waitTime = $resetTimestamp - $currentTimestamp;
155
                Cache::put('api_rate_limit', true, $waitTime);
156
            }
157
        }
158
    }
159
160
161
    /**
162
     * @param  string  $method
163
     * @param  string  $uri
164
     * @param  array  $options
165
     * @param $response
166
     * @return void
167
     */
168
    protected function logRequest(string $method, string $uri, array $options, $response): void
169
    {
170
        $status = $response instanceof ResponseInterface ? $response->getStatusCode() : null;
171
        $responseBody = $response instanceof ResponseInterface ? (string) $response->getBody() : null;
172
173
        LaraClientLog::create([
174
            'endpoint' => $uri,
175
            'method' => $method,
176
            'request_payload' => json_encode($options),
177
            'response_status' => $status,
178
            'response_body' => $responseBody,
179
            'created_at' => now()
180
        ]);
181
    }
182
183
    /**
184
     * @param $uri
185
     * @return string
186
     */
187
    protected function getFullUrl($uri): string
188
    {
189
        $fullUrl = $uri;
190
        if (!preg_match('/^https?:\/\//', $uri)) {
191
            $fullUrl = $this->config['base_uri'].$uri;
192
        }
193
        return $fullUrl;
194
    }
195
}
196