Completed
Pull Request — master (#267)
by
unknown
10:23
created

HttpRequest::http_build_query_for_curl()   B

Complexity

Conditions 7
Paths 10

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 9
nc 10
nop 3
dl 0
loc 14
rs 8.2222
c 0
b 0
f 0
1
<?php
2
namespace Qiniu\Rtc;
3
4
use \Qiniu\Rtc\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
        $lowerCaseFinalHeaders = array_change_key_case($finalHeaders);
0 ignored issues
show
Unused Code introduced by
$lowerCaseFinalHeaders is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

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