Passed
Push — master ( 82e9fe...cecb4c )
by Sheldon
04:44
created

Request::fsockgetExecute()   F

Complexity

Conditions 20
Paths 19200

Size

Total Lines 99

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 20
nc 19200
nop 0
dl 0
loc 99
rs 0
c 0
b 0
f 0

How to fix   Long Method    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
 * Created by PhpStorm.
4
 * User: sheldon
5
 * Date: 18-6-11
6
 * Time: 下午2:28.
7
 */
8
9
namespace MiotApi\Util;
10
11
class Request
12
{
13
    protected $hasCurl;
14
    protected $useCurl;
15
    protected $useBasicAuth;
16
    protected $HTTPVersion;
17
    protected $host;
18
    protected $port;
19
    protected $url;
20
    protected $uri;
21
    protected $headers;
22
    protected $data;
23
    protected $type;
24
    protected $query;
25
    protected $timeout;
26
    protected $error;
27
    protected $response;
28
    protected $responseText;
29
    protected $responseHeaders;
30
    protected $executed;
31
    protected $fsock;
32
    protected $curl;
33
    protected $additionalCurlOpts;
34
    protected $authUsername;
35
    protected $authPassword;
36
37
    /**
38
     * Request constructor.
39
     *
40
     * @param string $host
41
     * @param string $uri
42
     * @param int    $port
43
     * @param bool   $useCurl
44
     * @param int    $timeout
45
     */
46
    public function __construct($host = '', $uri = '/', $port = 80, $useCurl = true, $timeout = 10)
47
    {
48
        if (!$host) {
49
            return false;
50
        }
51
        $this->hasCurl = function_exists('curl_init');
52
        $this->useCurl = $this->hasCurl ? ($useCurl ? $useCurl : false) : false;
53
        $this->type = 'GET';
54
        $this->HTTPVersion = '1.1';
55
        $this->host = $host ? $host : $_SERVER['HTTP_HOST'];
56
        $this->uri = $uri;
57
        $this->port = $port;
58
        $this->timeout = $timeout;
59
        $this->setHeader('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8');
60
        $this->setHeader('Accept-Language', 'en-us,en;q=0.5');
61
        $this->setHeader('Accept-Encoding', 'deflate');
62
        $this->setHeader('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7');
63
        $this->setHeader('User-Agent', 'Mozilla/5.0 Firefox/3.6.12');
64
        $this->setHeader('Connection', 'close');
65
66
        return $this;
67
    }
68
69
    /**
70
     * 设置header头.
71
     *
72
     * @param $header
73
     * @param $content
74
     *
75
     * @return $this
76
     */
77
    public function setHeader($header, $content)
78
    {
79
        $this->headers[$header] = $content;
80
81
        return $this;
82
    }
83
84
    public static function curlHeaders()
85
    {
86
        return [
87
            'User-Agent' => CURLOPT_USERAGENT,
88
        ];
89
    }
90
91
    /**
92
     * 设置请求的host.
93
     *
94
     * @param $host
95
     *
96
     * @return $this
97
     */
98
    public function setHost($host)
99
    {
100
        $this->host = $host;
101
102
        return $this;
103
    }
104
105
    /**
106
     * 设置请求的URI.
107
     *
108
     * @param $uri
109
     *
110
     * @return $this
111
     */
112
    public function setRequestURI($uri)
113
    {
114
        $this->uri = $uri;
115
116
        return $this;
117
    }
118
119
    /**
120
     * 设置请求的端口.
121
     *
122
     * @param $port
123
     *
124
     * @return $this
125
     */
126
    public function setPort($port)
127
    {
128
        $this->port = $port;
129
130
        return $this;
131
    }
132
133
    /**
134
     * 设置请求的超时时间.
135
     *
136
     * @param $timeout
137
     *
138
     * @return $this
139
     */
140
    public function setTimeout($timeout)
141
    {
142
        $this->timeout = $timeout;
143
144
        return $this;
145
    }
146
147
    /**
148
     * 设置请求的参数.
149
     *
150
     * @param $get
151
     *
152
     * @return $this
153
     */
154
    public function setQueryParams($get)
155
    {
156
        $this->query = $get;
157
158
        return $this;
159
    }
160
161
    /**
162
     * 设置是否使用curl.
163
     *
164
     * @param $use
165
     *
166
     * @return $this
167
     */
168
    public function setUseCurl($use)
169
    {
170
        if ($use && $this->hasCurl) {
171
            $this->useCurl = true;
172
        } else {
173
            $this->useCurl = false;
174
        }
175
176
        return $this;
177
    }
178
179
    /**
180
     * 设置请求类型.
181
     *
182
     * @param $type
183
     *
184
     * @return $this
185
     */
186
    public function setType($type)
187
    {
188
        if (in_array($type, ['POST', 'GET', 'PUT', 'DELETE'])) {
189
            $this->type = $type;
190
        }
191
192
        return $this;
193
    }
194
195
    /**
196
     * 设置数据.
197
     *
198
     * @param $data
199
     *
200
     * @return $this
201
     */
202
    public function setData($data)
203
    {
204
        $this->data = $data;
205
206
        return $this;
207
    }
208
209
    /**
210
     * 设置请求的url.
211
     *
212
     * @param $url
213
     *
214
     * @return $this
215
     */
216
    public function setUrl($url)
217
    {
218
        $this->url = $url;
219
220
        return $this;
221
    }
222
223
    /**
224
     * 设置curl的参数.
225
     *
226
     * @param $option
227
     * @param $value
228
     */
229
    public function setAdditionalCurlOpt($option, $value)
230
    {
231
        if (is_array($option)) {
232
            foreach ($option as $opt => $val) {
233
                $this->setAdditionalCurlOpt($opt, $val);
234
            }
235
        } else {
236
            $this->additionalCurlOpts[$option] = $value;
237
        }
238
    }
239
240
    /**
241
     * 设置认证信息.
242
     *
243
     * @param $set
244
     * @param string | null $username
245
     * @param string | null $password
246
     */
247
    public function setUseBasicAuth($set, $username = null, $password = null)
248
    {
249
        $this->useBasicAuth = $set;
250
        if ($username) {
251
            $this->setAuthUsername($username);
252
        }
253
        if ($password) {
254
            $this->setAuthPassword($password);
255
        }
256
    }
257
258
    public function setAuthUsername($username = null)
259
    {
260
        $this->authUsername = $username;
261
    }
262
263
    public function setAuthPassword($password = null)
264
    {
265
        $this->authPassword = $password;
266
    }
267
268
    public function execute()
269
    {
270
        if ($this->useCurl) {
271
            $this->curlExecute();
272
        } else {
273
            $this->fsockgetExecute();
274
        }
275
276
        return $this;
277
    }
278
279
    /**
280
     * curl请求方式.
281
     */
282
    protected function curlExecute()
283
    {
284
        $uri = $this->uri;
285
        $host = $this->host;
286
        $type = $this->type;
287
        $port = $this->port;
288
        $data = property_exists($this, 'data') ? $this->param($this->data) : false;
289
        //$timeout = $this->timeout;
290
        // Initiate cURL.
291
        $ch = curl_init();
292
        // Set request type.
293
        if ($type === 'GET') {
294
            curl_setopt($ch, CURLOPT_HTTPGET, true);
295
        } elseif ($type === 'POST') {
296
            curl_setopt($ch, CURLOPT_POST, true);
297
            if ($data) {
298
                curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
299
            }
300
        } elseif ($type === 'PUT') {
301
            //curl_setopt($ch, CURLOPT_PUT, true);
302
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $type);
303
        } else {
304
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $type);
305
        }
306
        // Grab query string.
307
        $query = property_exists($this, 'query') && $this->query ? '?'.$this->param($this->query) : '';
308
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
309
        // Set additional headers.
310
        $headers = [];
311
        foreach ($this->headers as $name => $val) {
312
            $headers[] = $name . ': ' . $val;
313
        }
314
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
315
        // Do stuff it it's HTTPS/SSL.
316
        if ($port == 443) {
317
            $protocol = 'https';
318
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
319
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
320
        } else {
321
            $protocol = 'http';
322
        }
323
        if (!empty($this->additionalCurlOpts)) {
324
            foreach ($this->additionalCurlOpts as $option => $value) {
325
                curl_setopt($ch, $option, $value);
326
            }
327
        }
328
        // Build and set URL.
329
        $url = $protocol . '://' . $host . $uri . $query;
330
        curl_setopt($ch, CURLOPT_URL, $url);
331
        curl_setopt($ch, CURLOPT_PORT, $port);
332
        // Add any authentication to the request.
333
        // Currently supports only HTTP Basic Auth.
334
        if ($this->useBasicAuth === true) {
335
            curl_setopt($ch, CURLOPT_USERPWD, $this->authUsername . ':' . $this->authPassword);
336
            curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
337
        }
338
        // Execute!
339
        $rsp = curl_exec($ch);
340
341
        $this->curl = $ch;
342
        $this->executed = true;
343
344
        // Handle an error.
345
        if (!$error = curl_error($ch)) {
346
            $this->response = ['responseText' => $rsp] + curl_getinfo($ch);
347
            $this->responseHeaders = curl_getinfo($ch);
348
            $this->responseText = $rsp;
349
        } else {
350
            $this->error = $error;
351
        }
352
    }
353
354
    /**
355
     * @param $data
356
     *
357
     * @return string
358
     */
359
    public function param($data)
360
    {
361
        $dataArray = [];
362
363
        if (!empty($data)) {
364
            foreach ($data as $key => $val) {
365
                if (!is_string($val)) {
366
                    $val = json_encode($val);
367
                }
368
                $dataArray[] = urlencode($key) . '=' . urlencode($val);
369
            }
370
        }
371
372
        return implode('&', $dataArray);
373
    }
374
375
    /**
376
     * fsock请求方式.
377
     */
378
    protected function fsockgetExecute()
379
    {
380
        $uri = $this->uri;
381
        $host = $this->host;
382
        $port = $this->port;
383
        $type = $this->type;
384
        $HTTPVersion = $this->HTTPVersion;
385
        $data = property_exists($this, 'data') ? $this->data : null;
386
        $crlf = "\r\n";
387
388
        $rsp = '';
389
390
        // Deal with the data first.
391
        if ($data && $type === 'POST') {
392
            $data = $this->param($data);
393
        } elseif ($data && $type === 'GET') {
394
            $get_data = $data;
395
            $data = $crlf;
396
        } else {
397
            $data = $crlf;
398
        }
399
        // Then add
400
        if ($type === 'POST') {
401
            $this->setHeader('Content-Type', 'application/x-www-form-urlencoded');
402
            $this->setHeader('Content-Length', strlen($data));
403
            $get_data = property_exists($this, 'query') && $this->query ? self::param($this->query) : false;
0 ignored issues
show
Bug Best Practice introduced by
The method MiotApi\Util\Request::param() is not static, but was called statically. ( Ignorable by Annotation )

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

403
            $get_data = property_exists($this, 'query') && $this->query ? self::/** @scrutinizer ignore-call */ param($this->query) : false;
Loading history...
404
        } else {
405
            $this->setHeader('Content-Type', 'text/plain');
406
            $this->setHeader('Content-Length', strlen($crlf));
407
        }
408
        if ($type === 'GET') {
409
            if (isset($get_data)) {
410
                $get_data = $data;
411
            } elseif ($this->query) {
412
                $get_data = self::param($this->query);
413
            }
414
        }
415
        if ($this->useBasicAuth === true) {
416
            $this->setHeader(
417
                'Authorization',
418
                'Basic ' . base64_encode($this->authUsername . ':' . $this->authPassword)
419
            );
420
        }
421
        $headers = $this->headers;
422
        $req = '';
423
        $req .= $type . ' ' . $uri . (isset($get_data) ? '?' . $get_data : '') . ' HTTP/' . $HTTPVersion . $crlf;
424
        $req .= 'Host: ' . $host . $crlf;
425
        foreach ($headers as $header => $content) {
426
            $req .= $header . ': ' . $content . $crlf;
427
        }
428
        $req .= $crlf;
429
        if ($type === 'POST') {
430
            $req .= $data;
431
        } else {
432
            $req .= $crlf;
433
        }
434
435
        // Construct hostname.
436
        $fsock_host = ($port == 443 ? 'ssl://' : '') . $host;
437
438
        // Open socket.
439
        $httpreq = @fsockopen($fsock_host, $port, $errno, $errstr, 30);
440
441
        // Handle an error.
442
        if (!$httpreq) {
0 ignored issues
show
introduced by
$httpreq is of type resource, thus it always evaluated to false.
Loading history...
443
            $this->error = $errno . ': ' . $errstr;
444
445
            return false;
446
        }
447
448
        // Send the request.
449
        fwrite($httpreq, $req);
450
451
        // Receive the response.
452
        while ($line = fgets($httpreq)) {
453
            $rsp .= $line;
454
        }
455
456
        // Extract the headers and the responseText.
457
        list($headers, $responseText) = explode($crlf . $crlf, $rsp);
458
459
        // Store the finalized response.
460
        $this->response = $rsp;
461
        $this->responseText = $responseText;
462
        $this->status = array_shift($headers);
463
464
        // Store the response headers.
465
        $headers = explode($crlf, $headers);
466
        $this->responseHeaders = [];
467
        foreach ($headers as $header) {
468
            list($key, $val) = explode(': ', $header);
469
            $this->responseHeaders[$key] = $val;
470
        }
471
472
        // Mark as executed.
473
        $this->executed = true;
474
475
        // Store the resource so we can close it later.
476
        $this->fsock = $httpreq;
477
    }
478
479
    public function close()
480
    {
481
        if (!$this->executed) {
482
            return false;
483
        }
484
        if ($this->useCurl) {
485
            $this->curlClose();
486
        } else {
487
            $this->fsockgetClose();
488
        }
489
    }
490
491
    protected function curlClose()
492
    {
493
        curl_close($this->curl);
494
    }
495
496
    protected function fsockgetClose()
497
    {
498
        fclose($this->fsock);
499
    }
500
501
    public function getError()
502
    {
503
        return $this->error;
504
    }
505
506
    public function getResponse()
507
    {
508
        if (!$this->executed) {
509
            return false;
510
        }
511
512
        return $this->response;
513
    }
514
515
    public function getResponseText()
516
    {
517
        if (!$this->executed) {
518
            return false;
519
        }
520
521
        return $this->responseText;
522
    }
523
524
    public function getAllResponseHeaders()
525
    {
526
        if (!$this->executed) {
527
            return false;
528
        }
529
530
        return $this->responseHeaders;
531
    }
532
533
    public function getResponseHeader($header)
534
    {
535
        if (!$this->executed) {
536
            return false;
537
        }
538
        $headers = $this->responseHeaders;
539
        if (array_key_exists($header, $headers)) {
540
            return $headers[$header];
541
        }
542
    }
543
}
544