Completed
Pull Request — master (#267)
by
unknown
08:50
created

HttpRequest   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 172
rs 9.6
c 0
b 0
f 0
wmc 32
lcom 1
cbo 1

9 Methods

Rating   Name   Duplication   Size   Complexity  
A verifyPeer() 0 4 1
A timeout() 0 4 1
A defaultHeader() 0 4 1
A clearDefaultHeaders() 0 4 1
B http_build_query_for_curl() 0 14 7
A getArrayFromQuerystring() 0 12 2
B encodeUrl() 0 17 7
A getHeader() 0 5 1
C send() 0 55 11
1
<?php
2
namespace QiniuRtc;
3
4
use \QiniuRtc\HttpResponse;
5
6
class HttpRequest
7
{
8
    const DELETE = "DELETE";
9
    const GET    = "GET";
10
    const POST   = "POST";
11
12
    private static $verifyPeer = false;
13
    private static $socketTimeout = null;
14
    private static $defaultHeaders = array();
15
16
    /**
17
     * Verify SSL peer
18
     * @param bool $enabled enable SSL verification, by default is false
19
     */
20
    public static function verifyPeer($enabled)
21
    {
22
        self::$verifyPeer = $enabled;
23
    }
24
25
    /**
26
     * Set a timeout
27
     * @param integer $seconds timeout value in seconds
28
     */
29
    public static function timeout($seconds)
30
    {
31
        self::$socketTimeout = $seconds;
32
    }
33
34
    /**
35
     * Set a new default header to send on every request
36
     * @param string $name header name
37
     * @param string $value header value
38
     */
39
    public static function defaultHeader($name, $value)
40
    {
41
        self::$defaultHeaders[$name] = $value;
42
    }
43
44
    /**
45
     * Clear all the default headers
46
     */
47
    public static function clearDefaultHeaders()
48
    {
49
        self::$defaultHeaders = array();
50
    }
51
52
    /**
53
     * This function is useful for serializing multidimensional arrays, and avoid getting
54
     * the "Array to string conversion" notice
55
     */
56
    public static function http_build_query_for_curl($arrays, &$new = array(), $prefix = null)
57
    {
58
        if (is_object($arrays)) {
59
            $arrays = get_object_vars($arrays);
60
        }
61
        foreach ($arrays as $key => $value) {
62
            $k = isset($prefix) ? $prefix . '[' . $key . ']' : $key;
63
            if (!$value instanceof \CURLFile and (is_array($value) or is_object($value))) {
0 ignored issues
show
Bug introduced by
The class CURLFile does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
64
                self::http_build_query_for_curl($value, $new, $k);
65
            } else {
66
                $new[$k] = $value;
67
            }
68
        }
69
    }
70
71
    private static function getArrayFromQuerystring($querystring)
72
    {
73
        $pairs = explode("&", $querystring);
74
        $vars  = array();
75
        foreach ($pairs as $pair) {
76
            $nv          = explode("=", $pair, 2);
77
            $name        = $nv[0];
78
            $value       = $nv[1];
79
            $vars[$name] = $value;
80
        }
81
        return $vars;
82
    }
83
84
    /**
85
     * Ensure that a URL is encoded and safe to use with cURL
86
     * @param  string $url URL to encode
87
     * @return string
88
     */
89
    private static function encodeUrl($url)
90
    {
91
        $url_parsed = parse_url($url);
92
        $scheme = $url_parsed['scheme'] . '://';
93
        $host   = $url_parsed['host'];
94
        $port   = (isset($url_parsed['port']) ? $url_parsed['port'] : null);
95
        $path   = (isset($url_parsed['path']) ? $url_parsed['path'] : null);
96
        $query  = (isset($url_parsed['query']) ? $url_parsed['query'] : null);
97
        if ($query != null) {
98
            $query = '?' . http_build_query(self::getArrayFromQuerystring($url_parsed['query']));
99
        }
100
        if ($port && $port[0] != ":") {
101
            $port = ":" . $port;
102
        }
103
        $result = $scheme . $host . $port . $path . $query;
104
        return $result;
105
    }
106
107
    private static function getHeader($key, $val)
108
    {
109
        $key = trim($key);
110
        return $key . ": " . $val;
111
    }
112
113
    /**
114
     * Send a cURL request
115
     * @param string $httpMethod HTTP method to use
116
     * @param string $url URL to send the request to
117
     * @param mixed $body request body
118
     * @param array $headers additional headers to send
119
     * @throws Exception if a cURL error occurs
120
     * @return HttpResponse
121
     */
122
    public static function send($httpMethod, $url, $body = null, $headers = array())
123
    {
124
        if ($headers == null) {
125
            $headers = array();
126
        }
127
        $annexHeaders = array();
128
        $finalHeaders = array_merge($headers, self::$defaultHeaders);
129
        foreach ($finalHeaders as $key => $val) {
130
            $annexHeaders[] = self::getHeader($key, $val);
131
        }
132
        $ch = curl_init();
133
        if ($httpMethod != self::GET) {
134
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $httpMethod);
135
            if (is_array($body) || $body instanceof Traversable) {
0 ignored issues
show
Bug introduced by
The class QiniuRtc\Traversable does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
136
                self::http_build_query_for_curl($body, $postBody);
137
                curl_setopt($ch, CURLOPT_POSTFIELDS, $postBody);
138
            } else {
139
                curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
140
            }
141
        } elseif (is_array($body)) {
142
            if (strpos($url, '?') !== false) {
143
                $url .= "&";
144
            } else {
145
                $url .= "?";
146
            }
147
            self::http_build_query_for_curl($body, $postBody);
148
            $url .= urldecode(http_build_query($postBody));
149
        }
150
        curl_setopt($ch, CURLOPT_URL, self::encodeUrl($url));
151
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
152
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
153
        curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
154
        curl_setopt($ch, CURLOPT_HTTPHEADER, $annexHeaders);
155
        curl_setopt($ch, CURLOPT_HEADER, true);
156
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, self::$verifyPeer);
157
        curl_setopt($ch, CURLOPT_ENCODING, ""); // If an empty string, "", is set, a header containing all supported encoding types is sent.
158
        if (self::$socketTimeout != null) {
159
            curl_setopt($ch, CURLOPT_TIMEOUT, self::$socketTimeout);
160
        }
161
        $response = curl_exec($ch);
162
        $error    = curl_error($ch);
163
        if ($error) {
164
            throw new \Exception($error);
165
        }
166
        // Split the full response in its headers and body
167
        $curl_info   = curl_getinfo($ch);
168
        $header_size = $curl_info["header_size"];
169
        $header      = substr($response, 0, $header_size);
170
        $body        = substr($response, $header_size);
171
        $httpCode    = $curl_info["http_code"];
172
        if ($httpCode >= 400) {
173
            throw new \Exception($body);
174
        }
175
        return new HttpResponse($httpCode, $body, $header);
176
    }
177
}
178