HttpClient::communicate()   C
last analyzed

Complexity

Conditions 12
Paths 32

Size

Total Lines 47
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 12
eloc 35
nc 32
nop 5
dl 0
loc 47
rs 6.9666
c 3
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Kore : Simple And Minimal Framework
4
 *
5
 */
6
7
namespace Kore;
8
9
use Kore\Log;
10
11
/**
12
 * HttpClient class
13
 *
14
 */
15
class HttpClient
16
{
17
    /**
18
     * connect timeout
19
     *
20
     * Used as the value of CURLOPT_CONNECTTIMEOUT.
21
     * If unspecified, the default is 300.
22
     * For unlimited, specify 0.
23
     * @var int
24
     */
25
    protected $connectTimeout = 300;
26
    /**
27
     * timeout
28
     *
29
     * Used as the value of CURLOPT_TIMEOUT.
30
     * If unspecified, the default is 300.
31
     * For unlimited, specify 0.
32
     * @var int
33
     */
34
    protected $timeout = 300;
35
36
    /**
37
     * Set connect timeout
38
     *
39
     * @param int $connectTimeout connect timeout
40
     * @return void
41
     */
42
    public function setConnectTimeout($connectTimeout)
43
    {
44
        $this->connectTimeout = $connectTimeout;
45
    }
46
47
    /**
48
     * Set timeout
49
     *
50
     * @param int $timeout timeout
51
     * @return void
52
     */
53
    public function setTimeout($timeout)
54
    {
55
        $this->timeout = $timeout;
56
    }
57
    
58
    /**
59
     * GET Communication
60
     *
61
     * @param string $url request url
62
     * @param array<mixed> $params request parameters
63
     * @param array<mixed> $headers request headers
64
     * @param string|null $userpwd user name and password
65
     * @return HttpResponse \Kore\HttpResponse
66
     * @throws \Exception
67
     * @see \Kore\HttpResponse
68
     */
69
    public function get($url, $params = array(), $headers = array(), $userpwd = null)
70
    {
71
        return $this->communicate('GET', $url, $params, $headers, $userpwd);
72
    }
73
74
    /**
75
     * POST Communication
76
     *
77
     * @param string $url request url
78
     * @param array<mixed> $params request parameters
79
     * @param array<mixed> $headers request headers
80
     * @param string|null $userpwd user name and password
81
     * @return HttpResponse \Kore\HttpResponse
82
     * @throws \Exception
83
     * @see \Kore\HttpResponse
84
     */
85
    public function post($url, $params = array(), $headers = array(), $userpwd = null)
86
    {
87
        return $this->communicate('POST', $url, $params, $headers, $userpwd);
88
    }
89
90
    /**
91
     * PUT Communication
92
     *
93
     * @param string $url request url
94
     * @param array<mixed> $params request parameters
95
     * @param array<mixed> $headers request headers
96
     * @param string|null $userpwd user name and password
97
     * @return HttpResponse \Kore\HttpResponse
98
     * @throws \Exception
99
     * @see \Kore\HttpResponse
100
     */
101
    public function put($url, $params = array(), $headers = array(), $userpwd = null)
102
    {
103
        return $this->communicate('PUT', $url, $params, $headers, $userpwd);
104
    }
105
106
    /**
107
     * PATCH Communication
108
     *
109
     * @param string $url request url
110
     * @param array<mixed> $params request parameters
111
     * @param array<mixed> $headers request headers
112
     * @param string|null $userpwd user name and password
113
     * @return HttpResponse \Kore\HttpResponse
114
     * @throws \Exception
115
     * @see \Kore\HttpResponse
116
     */
117
    public function patch($url, $params = array(), $headers = array(), $userpwd = null)
118
    {
119
        return $this->communicate('PATCH', $url, $params, $headers, $userpwd);
120
    }
121
122
    /**
123
     * DELETE Communication
124
     *
125
     * @param string $url request url
126
     * @param array<mixed> $params request parameters
127
     * @param array<mixed> $headers request headers
128
     * @param string|null $userpwd user name and password
129
     * @return HttpResponse \Kore\HttpResponse
130
     * @throws \Exception
131
     * @see \Kore\HttpResponse
132
     */
133
    public function delete($url, $params = array(), $headers = array(), $userpwd = null)
134
    {
135
        return $this->communicate('DELETE', $url, $params, $headers, $userpwd);
136
    }
137
138
    /**
139
     * Communication Processing
140
     *
141
     * @param string $method http method
142
     * @param string $url request url
143
     * @param array<mixed> $params request parameters
144
     * @param array<mixed> $headers request headers
145
     * @param string|null $userpwd user name and password
146
     * @return HttpResponse \Kore\HttpResponse
147
     * @throws \Exception
148
     * @see \Kore\HttpResponse
149
     */
150
    protected function communicate($method, $url, $params = array(), $headers = array(), $userpwd = null)
151
    {
152
        $headers = $this->buildHeader($headers);
153
        
154
        $curl = curl_init();
155
156
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
157
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
158
        curl_setopt($curl, CURLOPT_HEADER, true);
159
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
160
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
161
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
162
        curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout);
163
        if ($method === 'GET') {
164
            $url = url_add_query($url, $params);
165
            curl_setopt($curl, CURLOPT_URL, $url);
166
        } elseif ($method === 'POST' || $method === 'PUT' || $method === 'PATCH' || $method === 'DELETE') {
167
            curl_setopt($curl, CURLOPT_URL, $url);
168
            $json_headers = preg_grep("/^Content-Type: application\/json/i", $headers);
169
            if ($json_headers !== false && count($json_headers) > 0) {
170
                $data = json_encode($params);
171
            } else {
172
                $data = http_build_query($params);
173
            }
174
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
175
        }
176
        if (!empty($headers)) {
177
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
178
        }
179
        if ($userpwd !== null) {
180
            curl_setopt($curl, CURLOPT_USERPWD, $userpwd);
181
        }
182
183
        $response = curl_exec($curl);
184
        $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
185
        $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
186
        $total_time = curl_getinfo($curl, CURLINFO_TOTAL_TIME);
187
188
        curl_close($curl);
189
190
        Log::debug(sprintf('[%s][%s][%ssec]', $url, $http_code, $total_time));
191
        if ($response === false || !is_string($response)) {
192
            throw new \Exception("Communication Error[$url($http_code)]");
193
        }
194
        $header = substr($response, 0, $header_size);
195
        $body = substr($response, $header_size);
196
        return new HttpResponse($http_code, $header, $body);
197
    }
198
199
    /**
200
     * Build headers
201
     *
202
     * Build the associative array headers into a curl-friendly format.
203
     * @param array<mixed> $headers headers
204
     * @return array<string> built headers
205
     */
206
    protected function buildHeader($headers)
207
    {
208
        $h = array();
209
        foreach ($headers as $key => $value) {
210
            if (is_string($key)) {
211
                $h[] = "$key: $value";
212
            } else {
213
                $h[] = $value;
214
            }
215
        }
216
        return $h;
217
    }
218
}
219
220
/**
221
 * HttpResponse class
222
 *
223
 */
224
class HttpResponse
225
{
226
    /**
227
     * __construct method
228
     *
229
     * @param int $httpCode http status code
230
     * @param string $header response headers
231
     * @param string $body response body
232
     * @return void
233
     */
234
    public function __construct($httpCode, $header, $body)
235
    {
236
        $this->httpCode = $httpCode;
237
        $this->header = $header;
238
        $this->body = $body;
239
    }
240
241
    /**
242
     * http status code
243
     *
244
     * @var int
245
     */
246
    private $httpCode;
247
    /**
248
     * response headers
249
     *
250
     * @var string
251
     */
252
    private $header;
253
    /**
254
     * response body
255
     *
256
     * @var string
257
     */
258
    private $body;
259
260
    /**
261
     * Get the http status code
262
     *
263
     * @return int http status code
264
     */
265
    public function getHttpCode()
266
    {
267
        return $this->httpCode;
268
    }
269
270
    /**
271
     * Get the response headers
272
     *
273
     * @return string response headers
274
     */
275
    public function getHeader()
276
    {
277
        return $this->header;
278
    }
279
280
    /**
281
     * Get the header value by specifying the header name
282
     *
283
     * @param string $key header name
284
     * @return string|null header value
285
     */
286
    public function getHeaderLine($key)
287
    {
288
        preg_match("/$key: (\S*)/i", $this->getHeader(), $matches);
289
        if (!isset($matches[1])) {
290
            return null;
291
        }
292
        return $matches[1];
293
    }
294
295
    /**
296
     * Get the response body
297
     *
298
     * @return string response body
299
     */
300
    public function getBody()
301
    {
302
        return $this->body;
303
    }
304
    
305
    /**
306
     * Get the response body in json format
307
     *
308
     * @return array<mixed> response body
309
     */
310
    public function getJsonBody()
311
    {
312
        return json_decode($this->getBody(), true);
313
    }
314
}
315