Completed
Push — master ( 564ad8...daabe2 )
by Hiraku
8s
created

HttpGetRequest::setConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
/*
3
 * hirak/prestissimo
4
 * @author Hiraku NAKANO
5
 * @license MIT https://github.com/hirak/prestissimo
6
 */
7
namespace Hirak\Prestissimo;
8
9
use Composer\IO;
10
use Composer\Composer;
11
use Composer\Downloader;
12
use Composer\Util\NoProxyPattern;
13
14
/**
15
 * Simple Container for http-get request
16
 */
17
class HttpGetRequest
18
{
19
    public $origin;
20
    public $scheme = 'http';
21
    public $host = 'example.com';
22
    public $port = 80;
23
    public $path = '/';
24
25
    public $query = array();
26
    public $headers = array();
27
28
    public $curlOpts = array();
29
30
    public $username = null;
31
    public $password = null;
32
33
    public $maybePublic = false;
34
    public $verbose = false;
35
36
    /** @internal */
37
    const TOKEN_LABEL = 'access_token';
38
39
    /**
40
     * normalize url and authentication info
41
     * @param string $origin domain text
42
     * @param string $url
43
     * @param IO\IOInterface $io
44
     */
45 15
    public function __construct($origin, $url, IO\IOInterface $io)
46
    {
47 15
        $this->origin = $origin;
48 15
        $this->importURL($url);
49 15
        $this->setupProxy();
50
51 15
        if ($this->username && $this->password) {
52 3
            $io->setAuthentication($origin, $this->username, $this->password);
53 15
        } elseif ($io->hasAuthentication($origin)) {
54 1
            $auth = $io->getAuthentication($origin);
55 1
            $this->username = $auth['username'];
56 1
            $this->password = $auth['password'];
57 1
        }
58 15
    }
59
60 15
    private function setupProxy()
0 ignored issues
show
Coding Style introduced by
setupProxy uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
61
    {
62
        // no_proxy skip
63 15
        if (isset($_SERVER['no_proxy'])) {
64 1
            $pattern = new NoProxyPattern($_SERVER['no_proxy']);
65 1
            if ($pattern->test($this->getURL())) {
66 1
                unset($this->curlOpts[CURLOPT_PROXY]);
67 1
                return;
68
            }
69 1
        }
70
71 15
        $httpProxy = self::issetOr($_SERVER, 'http_proxy', 'HTTP_PROXY');
72 15
        if ($httpProxy && $this->scheme === 'http') {
73 1
            $this->curlOpts[CURLOPT_PROXY] = $httpProxy;
74 1
            return;
75
        }
76
77 14
        $httpsProxy = self::issetOr($_SERVER, 'https_proxy', 'HTTPS_PROXY');
78 14
        if ($httpsProxy && $this->scheme === 'https') {
79 1
            $this->curlOpts[CURLOPT_PROXY] = $httpsProxy;
80 1
            return;
81
        }
82
83 13
        unset($this->curlOpts[CURLOPT_PROXY]);
84 13
        unset($this->curlOpts[CURLOPT_PROXYUSERPWD]);
85 13
    }
86
87 15
    private static function issetOr(array $arr, $key1, $key2)
88
    {
89 15
        if (isset($arr[$key1])) {
90 2
            return $arr[$key1];
91
        }
92 15
        if (isset($arr[$key2])) {
93 2
            return $arr[$key2];
94
        }
95 14
        return null;
96
    }
97
98
    /**
99
     * @param string $url
100
     */
101 15
    public function importURL($url)
102
    {
103 15
        $struct = parse_url($url);
104
        // @codeCoverageIgnoreStart
105
        if (!$struct) {
106
            throw new \InvalidArgumentException("$url is not valid URL");
107
        }
108
        // @codeCoverageIgnoreEnd
109
110 15
        $this->scheme = self::setOr($struct, 'scheme');
111 15
        $this->host = self::setOr($struct, 'host');
112 15
        $this->port = self::setOr($struct, 'port');
113 15
        $this->path = self::setOr($struct, 'path');
114 15
        $this->username = self::setOr($struct, 'user');
115 15
        $this->password = self::setOr($struct, 'pass');
116
117 15
        if (!empty($struct['query'])) {
118 3
            parse_str($struct['query'], $this->query);
119 3
        }
120 15
    }
121
122
123
    /**
124
     * @param array $struct
125
     * @param string $key
126
     * @param string $default
127
     * @return mixed
128
     */
129 15
    private static function setOr(array $struct, $key, $default = null)
130
    {
131 15
        if (!empty($struct[$key])) {
132 15
            return $struct[$key];
133
        }
134
135 15
        return $default;
136
    }
137
138
    /**
139
     * process option for RemortFileSystem
140
     * @param array $options
141
     * @return void
142
     */
143 2
    public function processRFSOption(array $options)
144
    {
145 2
        if (isset($options[static::TOKEN_LABEL])) {
146 2
            $this->query['access_token'] = $options[static::TOKEN_LABEL];
147 2
        }
148 2
    }
149
150
    /**
151
     * @return array
152
     */
153 4
    public function getCurlOpts()
154
    {
155 4
        $headers = $this->headers;
156 4
        if ($this->username && $this->password) {
157 1
            foreach ($headers as $i => $header) {
158
                if (0 === strpos($header, 'Authorization:')) {
159
                    unset($headers[$i]);
160
                }
161 1
            }
162 1
            $headers[] = 'Authorization: Basic ' . base64_encode("$this->username:$this->password");
163 1
        }
164
165 4
        $curlOpts = $this->curlOpts + array(
166 4
            CURLOPT_HTTPGET => true,
167 4
            CURLOPT_FOLLOWLOCATION => true,
168 4
            CURLOPT_MAXREDIRS => 20,
169 4
            CURLOPT_ENCODING => 'gzip',
170 4
            CURLOPT_HTTPHEADER => $headers,
171 4
            CURLOPT_USERAGENT => $this->genUA(),
172 4
            CURLOPT_VERBOSE => (bool)$this->verbose,
173 4
            CURLOPT_URL => $this->getUrl(),
174 4
        );
175 4
        unset($curlOpts[CURLOPT_USERPWD]);
176
177 4
        if ($ciphers = $this->nssCiphers()) {
178
            $curlOpts[CURLOPT_SSL_CIPHER_LIST] = $ciphers;
179
        }
180
181 4
        return $curlOpts;
182
    }
183
184
    /**
185
     * enable ECC cipher suites in cURL/NSS
186
     */
187 4
    public function nssCiphers()
188
    {
189 4
        static $cache;
190 4
        if (isset($cache)) {
191 3
            return $cache;
192
        }
193 2
        $ver = curl_version();
194 2
        if (preg_match('/^NSS.*Basic ECC$/', $ver['ssl_version'])) {
195
            $ciphers = file(__DIR__ . '/../res/nss_ciphers.txt', \FILE_IGNORE_NEW_LINES | \FILE_SKIP_EMPTY_LINES);
196
            return $cache = implode(',', $ciphers);
197
        }
198 2
        return $cache = false;
199
    }
200
201 8
    public function getURL()
202
    {
203 8
        $url = '';
204 8
        if ($this->scheme) {
205 8
            $url .= "$this->scheme://";
206 8
        }
207 8
        $url .= $this->host;
208
209 8
        if ($this->port) {
210 3
            $url .= ":$this->port";
211 3
        }
212
213 8
        $url .= $this->path;
214
215 8
        if ($this->query) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->query of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
216 3
            $url .= '?' . http_build_query($this->query);
217 3
        }
218
219 8
        return $url;
220
    }
221
222
    /**
223
     * @return string
224
     */
225 4
    public static function genUA()
226
    {
227 4
        static $ua;
228 4
        if ($ua) {
229 3
            return $ua;
230
        }
231 2
        $phpVersion = defined('HHVM_VERSION') ? 'HHVM ' . HHVM_VERSION : 'PHP ' . PHP_VERSION;
232
233 2
        return $ua = sprintf(
234 2
            'Composer/%s (%s; %s; %s)',
235 2
            str_replace('@package_version@', 'source', Composer::VERSION),
236 2
            php_uname('s'),
237 2
            php_uname('r'),
238
            $phpVersion
239 2
        );
240
    }
241
}
242