| Total Complexity | 130 |
| Total Lines | 938 |
| Duplicated Lines | 0 % |
| Changes | 0 | ||
Complex classes like requests often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use requests, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 59 | class requests |
||
| 60 | { |
||
| 61 | const VERSION = '2.0.1'; |
||
| 62 | |||
| 63 | protected static $ch = null; |
||
| 64 | |||
| 65 | /**** Public variables ****/ |
||
| 66 | |||
| 67 | /* user definable vars */ |
||
| 68 | |||
| 69 | public static $timeout = 15; |
||
| 70 | public static $encoding = null; |
||
| 71 | public static $input_encoding = null; |
||
| 72 | public static $output_encoding = null; |
||
| 73 | public static $cookies = array(); // array of cookies to pass |
||
| 74 | // $cookies['username'] = "seatle"; |
||
| 75 | public static $rawheaders = array(); // array of raw headers to send |
||
| 76 | public static $domain_cookies = array(); // array of cookies for domain to pass |
||
| 77 | public static $hosts = array(); // random host binding for make request faster |
||
| 78 | public static $headers = array(); // headers returned from server sent here |
||
| 79 | public static $useragents = array("requests/2.0.0"); // random agent we masquerade as |
||
| 80 | public static $client_ips = array(); // random ip we masquerade as |
||
| 81 | public static $proxies = array(); // random proxy ip |
||
| 82 | public static $raw = ""; // head + body content returned from server sent here |
||
| 83 | public static $head = ""; // head content |
||
| 84 | public static $content = ""; // The body before encoding |
||
| 85 | public static $text = ""; // The body after encoding |
||
| 86 | public static $info = array(); // curl info |
||
| 87 | public static $history = 302; // http request status before redirect. ex:30x |
||
| 88 | public static $status_code = 0; // http request status |
||
| 89 | public static $error = ""; // error messages sent here |
||
| 90 | |||
| 91 | /** |
||
| 92 | * set timeout |
||
| 93 | * $timeout 为数组时会分别设置connect和read |
||
| 94 | * |
||
| 95 | * @param init or array $timeout |
||
|
|
|||
| 96 | * @return |
||
| 97 | */ |
||
| 98 | public static function set_timeout($timeout) |
||
| 99 | { |
||
| 100 | self::$timeout = $timeout; |
||
| 101 | } |
||
| 102 | |||
| 103 | /** |
||
| 104 | * 设置代理 |
||
| 105 | * 如果代理有多个,请求时会随机使用 |
||
| 106 | * |
||
| 107 | * @param mixed $proxies |
||
| 108 | * array ( |
||
| 109 | * 'socks5://user1:pass2@host:port', |
||
| 110 | * 'socks5://user2:pass2@host:port' |
||
| 111 | *) |
||
| 112 | * @return void |
||
| 113 | * @author seatle <[email protected]> |
||
| 114 | * @created time :2016-09-18 10:17 |
||
| 115 | */ |
||
| 116 | public static function set_proxy($proxy) |
||
| 117 | { |
||
| 118 | self::$proxies = is_array($proxy) ? $proxy : array($proxy); |
||
| 119 | } |
||
| 120 | |||
| 121 | /** |
||
| 122 | * 删除代理 |
||
| 123 | * 因为每个链接信息里面都有代理信息,有的链接需要,有的不需要,所以必须提供一个删除功能 |
||
| 124 | * |
||
| 125 | * @return void |
||
| 126 | * @author seatle <[email protected]> |
||
| 127 | * @created time :2018-07-16 17:59 |
||
| 128 | */ |
||
| 129 | public static function del_proxy() |
||
| 130 | { |
||
| 131 | self::$proxies = array(); |
||
| 132 | } |
||
| 133 | |||
| 134 | /** |
||
| 135 | * 自定义请求头部 |
||
| 136 | * 请求头内容可以用 requests::$rawheaders 来获取 |
||
| 137 | * 比如获取Content-Type:requests::$rawheaders['Content-Type'] |
||
| 138 | * |
||
| 139 | * @param string $headers |
||
| 140 | * @return void |
||
| 141 | */ |
||
| 142 | public static function set_header($key, $value) |
||
| 143 | { |
||
| 144 | self::$rawheaders[$key] = $value; |
||
| 145 | } |
||
| 146 | |||
| 147 | /** |
||
| 148 | * 设置全局COOKIE |
||
| 149 | * |
||
| 150 | * @param string $cookie |
||
| 151 | * @return void |
||
| 152 | */ |
||
| 153 | public static function set_cookie($key, $value, $domain = '') |
||
| 154 | { |
||
| 155 | if (empty($key)) |
||
| 156 | { |
||
| 157 | return false; |
||
| 158 | } |
||
| 159 | if (!empty($domain)) |
||
| 160 | { |
||
| 161 | self::$domain_cookies[$domain][$key] = $value; |
||
| 162 | } |
||
| 163 | else |
||
| 164 | { |
||
| 165 | self::$cookies[$key] = $value; |
||
| 166 | } |
||
| 167 | return true; |
||
| 168 | } |
||
| 169 | |||
| 170 | /** |
||
| 171 | * 批量设置全局cookie |
||
| 172 | * |
||
| 173 | * @param mixed $cookies |
||
| 174 | * @param string $domain |
||
| 175 | * @return void |
||
| 176 | * @author seatle <[email protected]> |
||
| 177 | * @created time :2017-08-03 18:06 |
||
| 178 | */ |
||
| 179 | public static function set_cookies($cookies, $domain = '') |
||
| 180 | { |
||
| 181 | $cookies_arr = explode(';', $cookies); |
||
| 182 | if (empty($cookies_arr)) |
||
| 183 | { |
||
| 184 | return false; |
||
| 185 | } |
||
| 186 | |||
| 187 | foreach ($cookies_arr as $cookie) |
||
| 188 | { |
||
| 189 | $cookie_arr = explode('=', $cookie, 2); |
||
| 190 | $key = $cookie_arr[0]; |
||
| 191 | $value = empty($cookie_arr[1]) ? '' : $cookie_arr[1]; |
||
| 192 | |||
| 193 | if (!empty($domain)) |
||
| 194 | { |
||
| 195 | self::$domain_cookies[$domain][$key] = $value; |
||
| 196 | } |
||
| 197 | else |
||
| 198 | { |
||
| 199 | self::$cookies[$key] = $value; |
||
| 200 | } |
||
| 201 | } |
||
| 202 | return true; |
||
| 203 | } |
||
| 204 | |||
| 205 | /** |
||
| 206 | * 获取单一Cookie |
||
| 207 | * |
||
| 208 | * @param mixed $name cookie名称 |
||
| 209 | * @param string $domain 不传则取全局cookie,就是手动set_cookie的cookie |
||
| 210 | * @return void |
||
| 211 | * @author seatle <[email protected]> |
||
| 212 | * @created time :2017-08-03 18:06 |
||
| 213 | */ |
||
| 214 | public static function get_cookie($name, $domain = '') |
||
| 215 | { |
||
| 216 | if (!empty($domain) && !isset(self::$domain_cookies[$domain])) |
||
| 217 | { |
||
| 218 | return ''; |
||
| 219 | } |
||
| 220 | $cookies = empty($domain) ? self::$cookies : self::$domain_cookies[$domain]; |
||
| 221 | return isset($cookies[$name]) ? $cookies[$name] : ''; |
||
| 222 | } |
||
| 223 | |||
| 224 | /** |
||
| 225 | * 获取Cookie数组 |
||
| 226 | * |
||
| 227 | * @param string $domain 不传则取全局cookie,就是手动set_cookie的cookie |
||
| 228 | * @return void |
||
| 229 | * @author seatle <[email protected]> |
||
| 230 | * @created time :2017-08-03 18:06 |
||
| 231 | */ |
||
| 232 | public static function get_cookies($domain = '') |
||
| 233 | { |
||
| 234 | if (!empty($domain) && !isset(self::$domain_cookies[$domain])) |
||
| 235 | { |
||
| 236 | return array(); |
||
| 237 | } |
||
| 238 | return empty($domain) ? self::$cookies : self::$domain_cookies[$domain]; |
||
| 239 | } |
||
| 240 | |||
| 241 | /** |
||
| 242 | * 删除Cookie |
||
| 243 | * |
||
| 244 | * @param string $domain 不传则删除全局Cookie |
||
| 245 | * @return void |
||
| 246 | * @author seatle <[email protected]> |
||
| 247 | * @created time :2017-08-03 18:06 |
||
| 248 | */ |
||
| 249 | public static function del_cookie($key, $domain = '') |
||
| 250 | { |
||
| 251 | if (empty($key)) |
||
| 252 | { |
||
| 253 | return false; |
||
| 254 | } |
||
| 255 | |||
| 256 | if (!empty($domain) && !isset(self::$domain_cookies[$domain])) |
||
| 257 | { |
||
| 258 | return false; |
||
| 259 | } |
||
| 260 | |||
| 261 | if (!empty($domain)) |
||
| 262 | { |
||
| 263 | if (isset(self::$domain_cookies[$domain][$key])) |
||
| 264 | { |
||
| 265 | unset(self::$domain_cookies[$domain][$key]); |
||
| 266 | } |
||
| 267 | } |
||
| 268 | else |
||
| 269 | { |
||
| 270 | if (isset(self::$cookies[$key])) |
||
| 271 | { |
||
| 272 | unset(self::$cookies[$key]); |
||
| 273 | } |
||
| 274 | } |
||
| 275 | return true; |
||
| 276 | } |
||
| 277 | |||
| 278 | /** |
||
| 279 | * 删除Cookie |
||
| 280 | * |
||
| 281 | * @param string $domain 不传则删除全局Cookie |
||
| 282 | * @return void |
||
| 283 | * @author seatle <[email protected]> |
||
| 284 | * @created time :2017-08-03 18:06 |
||
| 285 | */ |
||
| 286 | public static function del_cookies($domain = '') |
||
| 304 | } |
||
| 305 | |||
| 306 | /** |
||
| 307 | * 设置随机的user_agent |
||
| 308 | * |
||
| 309 | * @param string $useragent |
||
| 310 | * @return void |
||
| 311 | */ |
||
| 312 | public static function set_useragent($useragent) |
||
| 313 | { |
||
| 314 | self::$useragents = is_array($useragent) ? $useragent : array($useragent); |
||
| 315 | } |
||
| 316 | |||
| 317 | /** |
||
| 318 | * set referer |
||
| 319 | * |
||
| 320 | */ |
||
| 321 | public static function set_referer($referer) |
||
| 322 | { |
||
| 323 | self::$rawheaders['Referer'] = $referer; |
||
| 324 | } |
||
| 325 | |||
| 326 | /** |
||
| 327 | * 设置伪造IP |
||
| 328 | * 传入数组则为随机IP |
||
| 329 | * @param string $ip |
||
| 330 | * @return void |
||
| 331 | */ |
||
| 332 | public static function set_client_ip($ip) |
||
| 335 | } |
||
| 336 | |||
| 337 | /** |
||
| 338 | * 删除伪造IP |
||
| 339 | * |
||
| 340 | * @return void |
||
| 341 | * @author seatle <[email protected]> |
||
| 342 | * @created time :2018-07-16 17:59 |
||
| 343 | */ |
||
| 344 | public static function del_client_ip() |
||
| 345 | { |
||
| 346 | self::$client_ips = array(); |
||
| 347 | } |
||
| 348 | |||
| 349 | /** |
||
| 350 | * 设置中文请求 |
||
| 351 | * |
||
| 352 | * @param string $lang |
||
| 353 | * @return void |
||
| 354 | */ |
||
| 355 | public static function set_accept_language($lang = 'zh-CN') |
||
| 356 | { |
||
| 357 | self::$rawheaders['Accept-Language'] = $lang; |
||
| 358 | } |
||
| 359 | |||
| 360 | /** |
||
| 361 | * 设置Hosts |
||
| 362 | * 负载均衡到不同的服务器,如果对方使用CDN,采用这个是最好的了 |
||
| 363 | * |
||
| 364 | * @param string $hosts |
||
| 365 | * @return void |
||
| 366 | */ |
||
| 367 | public static function set_hosts($host, $ips = array()) |
||
| 368 | { |
||
| 369 | $ips = is_array($ips) ? $ips : array($ips); |
||
| 370 | self::$hosts[$host] = $ips; |
||
| 371 | } |
||
| 372 | |||
| 373 | /** |
||
| 374 | * 分割返回的header和body |
||
| 375 | * header用来判断编码和获取Cookie |
||
| 376 | * body用来判断编码,得到编码前和编码后的内容 |
||
| 377 | * |
||
| 378 | * @return void |
||
| 379 | * @author seatle <[email protected]> |
||
| 380 | * @created time :2017-08-03 18:06 |
||
| 381 | */ |
||
| 382 | public static function split_header_body() |
||
| 383 | { |
||
| 384 | $head = $body = ''; |
||
| 385 | $head = substr(self::$raw, 0, self::$info['header_size']); |
||
| 386 | $body = substr(self::$raw, self::$info['header_size']); |
||
| 387 | // http header |
||
| 388 | self::$head = $head; |
||
| 389 | // The body before encoding |
||
| 390 | self::$content = $body; |
||
| 391 | |||
| 392 | //$http_headers = array(); |
||
| 393 | //// 解析HTTP数据流 |
||
| 394 | //if (!empty(self::$raw)) |
||
| 395 | //{ |
||
| 396 | //self::get_response_cookies($domain); |
||
| 397 | //// body里面可能有 \r\n\r\n,但是第一个一定是HTTP Header,去掉后剩下的就是body |
||
| 398 | //$array = explode("\r\n\r\n", self::$raw); |
||
| 399 | //foreach ($array as $k=>$v) |
||
| 400 | //{ |
||
| 401 | //// post 方法会有两个http header:HTTP/1.1 100 Continue、HTTP/1.1 200 OK |
||
| 402 | //if (preg_match("#^HTTP/.*? 100 Continue#", $v)) |
||
| 403 | //{ |
||
| 404 | //unset($array[$k]); |
||
| 405 | //continue; |
||
| 406 | //} |
||
| 407 | //if (preg_match("#^HTTP/.*? \d+ #", $v)) |
||
| 408 | //{ |
||
| 409 | //$header = $v; |
||
| 410 | //unset($array[$k]); |
||
| 411 | //$http_headers = self::get_response_headers($v); |
||
| 412 | //} |
||
| 413 | //} |
||
| 414 | //$body = implode("\r\n\r\n", $array); |
||
| 415 | //} |
||
| 416 | |||
| 417 | // 设置了输出编码的转码,注意: xpath只支持utf-8,iso-8859-1 不要转,他本身就是utf-8 |
||
| 418 | $body = self::encoding($body); //自动转码 |
||
| 419 | // 转码后 |
||
| 420 | self::$encoding = self::$output_encoding; |
||
| 421 | |||
| 422 | // The body after encoding |
||
| 423 | self::$text = $body; |
||
| 424 | return array($head, $body); |
||
| 425 | } |
||
| 426 | |||
| 427 | /** |
||
| 428 | * 获得域名相对应的Cookie |
||
| 429 | * |
||
| 430 | * @param mixed $header |
||
| 431 | * @param mixed $domain |
||
| 432 | * @return void |
||
| 433 | * @author seatle <[email protected]> |
||
| 434 | * @created time :2017-08-03 18:06 |
||
| 435 | */ |
||
| 436 | public static function get_response_cookies($header, $domain) |
||
| 437 | { |
||
| 438 | // 解析Cookie并存入 self::$cookies 方便调用 |
||
| 439 | preg_match_all("/.*?Set\-Cookie: ([^\r\n]*)/i", $header, $matches); |
||
| 440 | $cookies = empty($matches[1]) ? array() : $matches[1]; |
||
| 441 | |||
| 442 | // 解析到Cookie |
||
| 443 | if (!empty($cookies)) |
||
| 444 | { |
||
| 445 | $cookies = implode(';', $cookies); |
||
| 446 | $cookies = explode(';', $cookies); |
||
| 447 | foreach ($cookies as $cookie) |
||
| 448 | { |
||
| 449 | $cookie_arr = explode('=', $cookie, 2); |
||
| 450 | // 过滤 httponly、secure |
||
| 451 | if (count($cookie_arr) < 2) |
||
| 452 | { |
||
| 453 | continue; |
||
| 454 | } |
||
| 455 | $cookie_name = !empty($cookie_arr[0]) ? trim($cookie_arr[0]) : ''; |
||
| 456 | if (empty($cookie_name)) |
||
| 457 | { |
||
| 458 | continue; |
||
| 459 | } |
||
| 460 | // 过滤掉domain路径 |
||
| 461 | if (in_array(strtolower($cookie_name), array('path', 'domain', 'expires', 'max-age'))) |
||
| 462 | { |
||
| 463 | continue; |
||
| 464 | } |
||
| 465 | self::$domain_cookies[$domain][trim($cookie_arr[0])] = trim($cookie_arr[1]); |
||
| 466 | } |
||
| 467 | } |
||
| 468 | } |
||
| 469 | |||
| 470 | /** |
||
| 471 | * 获得response header |
||
| 472 | * 此方法占时没有用到 |
||
| 473 | * |
||
| 474 | * @param mixed $header |
||
| 475 | * @return void |
||
| 476 | * @author seatle <[email protected]> |
||
| 477 | * @created time :2017-08-03 18:06 |
||
| 478 | */ |
||
| 479 | public static function get_response_headers($header) |
||
| 480 | { |
||
| 481 | $headers = array(); |
||
| 482 | $header_lines = explode("\n", $header); |
||
| 483 | if (!empty($header_lines)) |
||
| 484 | { |
||
| 485 | foreach ($header_lines as $line) |
||
| 486 | { |
||
| 487 | $header_arr = explode(':', $line, 2); |
||
| 488 | $key = empty($header_arr[0]) ? '' : trim($header_arr[0]); |
||
| 489 | $val = empty($header_arr[1]) ? '' : trim($header_arr[1]); |
||
| 490 | if (empty($key) || empty($val)) |
||
| 491 | { |
||
| 492 | continue; |
||
| 493 | } |
||
| 494 | $headers[$key] = $val; |
||
| 495 | } |
||
| 496 | } |
||
| 497 | self::$headers = $headers; |
||
| 498 | return self::$headers; |
||
| 499 | } |
||
| 500 | |||
| 501 | /** |
||
| 502 | * 获取编码 |
||
| 503 | * @param $string |
||
| 504 | * @return string |
||
| 505 | */ |
||
| 506 | public static function get_encoding($string) |
||
| 507 | { |
||
| 508 | $encoding = mb_detect_encoding($string, array('UTF-8', 'GBK', 'GB2312', 'LATIN1', 'ASCII', 'BIG5', 'ISO-8859-1')); |
||
| 509 | return strtolower($encoding); |
||
| 510 | } |
||
| 511 | |||
| 512 | /** |
||
| 513 | * 移除页面head区域代码 |
||
| 514 | * @param $html |
||
| 515 | * @return mixed |
||
| 516 | */ |
||
| 517 | private static function _remove_head($html) |
||
| 518 | { |
||
| 519 | return preg_replace('/<head.+?>.+<\/head>/is', '<head></head>', $html); |
||
| 520 | } |
||
| 521 | |||
| 522 | /** |
||
| 523 | * 简单的判断一下参数是否为一个URL链接 |
||
| 524 | * @param string $str |
||
| 525 | * @return boolean |
||
| 526 | */ |
||
| 527 | private static function _is_url($url) |
||
| 528 | { |
||
| 529 | //$pattern = '/^http(s)?:\\/\\/.+/'; |
||
| 530 | $pattern = "/\b(([\w-]+:\/\/?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|\/)))/"; |
||
| 531 | if (preg_match($pattern, $url)) |
||
| 532 | { |
||
| 533 | return true; |
||
| 534 | } |
||
| 535 | return false; |
||
| 536 | } |
||
| 537 | |||
| 538 | /** |
||
| 539 | * 初始化 CURL |
||
| 540 | * |
||
| 541 | */ |
||
| 542 | public static function init() |
||
| 543 | { |
||
| 544 | if (!is_resource ( self::$ch )) |
||
| 545 | { |
||
| 546 | self::$ch = curl_init (); |
||
| 547 | curl_setopt( self::$ch, CURLOPT_RETURNTRANSFER, true ); |
||
| 548 | curl_setopt( self::$ch, CURLOPT_HEADER, false ); |
||
| 549 | curl_setopt( self::$ch, CURLOPT_USERAGENT, "phpspider-requests/".self::VERSION ); |
||
| 550 | // 如果设置了两个时间,就分开设置 |
||
| 551 | if (is_array(self::$timeout)) |
||
| 552 | { |
||
| 553 | curl_setopt( self::$ch, CURLOPT_CONNECTTIMEOUT, self::$timeout[0] ); |
||
| 554 | curl_setopt( self::$ch, CURLOPT_TIMEOUT, self::$timeout[1]); |
||
| 555 | } |
||
| 556 | else |
||
| 557 | { |
||
| 558 | curl_setopt(self::$ch, CURLOPT_CONNECTTIMEOUT, ceil(self::$timeout / 2)); |
||
| 559 | curl_setopt(self::$ch, CURLOPT_TIMEOUT, self::$timeout); |
||
| 560 | } |
||
| 561 | curl_setopt(self::$ch, CURLOPT_MAXREDIRS, 5); //maximum number of redirects allowed |
||
| 562 | // 在多线程处理场景下使用超时选项时,会忽略signals对应的处理函数,但是无耐的是还有小概率的crash情况发生 |
||
| 563 | curl_setopt( self::$ch, CURLOPT_NOSIGNAL, true); |
||
| 564 | } |
||
| 565 | return self::$ch; |
||
| 566 | } |
||
| 567 | |||
| 568 | /** |
||
| 569 | * get 请求 |
||
| 570 | */ |
||
| 571 | public static function get($url, $fields = array(), $allow_redirects = true, $cert = NULL) |
||
| 572 | { |
||
| 573 | self::init (); |
||
| 574 | return self::request($url, 'get', $fields, NULL, $allow_redirects, $cert); |
||
| 575 | } |
||
| 576 | |||
| 577 | /** |
||
| 578 | * post 请求 |
||
| 579 | * $fields 有三种类型:1、数组;2、http query;3、json |
||
| 580 | * 1、array('name'=>'yangzetao') |
||
| 581 | * 2、http_build_query(array('name'=>'yangzetao')) |
||
| 582 | * 3、json_encode(array('name'=>'yangzetao')) |
||
| 583 | * 前两种是普通的post,可以用$_POST方式获取 |
||
| 584 | * 第三种是post stream( json rpc,其实就是webservice ) |
||
| 585 | * 虽然是post方式,但是只能用流方式 http://input 后者 $HTTP_RAW_POST_DATA 获取 |
||
| 586 | * |
||
| 587 | * @param mixed $url |
||
| 588 | * @param array $fields |
||
| 589 | * @param mixed $proxies |
||
| 590 | * @static |
||
| 591 | * @access public |
||
| 592 | * @return void |
||
| 593 | */ |
||
| 594 | public static function post($url, $fields = array(), $files = array(), $allow_redirects = true, $cert = NULL) |
||
| 595 | { |
||
| 596 | self::init (); |
||
| 597 | return self::request($url, 'POST', $fields, $files, $allow_redirects, $cert); |
||
| 598 | } |
||
| 599 | |||
| 600 | public static function put($url, $fields = array(), $allow_redirects = true, $cert = NULL) |
||
| 601 | { |
||
| 602 | self::init (); |
||
| 603 | return self::request($url, 'PUT', $fields, $allow_redirects, $cert); |
||
| 604 | } |
||
| 605 | |||
| 606 | public static function delete($url, $fields = array(), $allow_redirects = true, $cert = NULL) |
||
| 607 | { |
||
| 608 | self::init (); |
||
| 609 | return self::request($url, 'DELETE', $fields, $allow_redirects, $cert); |
||
| 610 | } |
||
| 611 | |||
| 612 | // 响应HTTP头域里的元信息 |
||
| 613 | // 此方法被用来获取请求实体的元信息而不需要传输实体主体(entity-body) |
||
| 614 | // 此方法经常被用来测试超文本链接的有效性,可访问性,和最近的改变。. |
||
| 615 | public static function head($url, $fields = array(), $allow_redirects = true, $cert = NULL) |
||
| 616 | { |
||
| 617 | self::init (); |
||
| 618 | self::request($url, 'HEAD', $fields, $allow_redirects, $cert); |
||
| 619 | } |
||
| 620 | |||
| 621 | public static function options($url, $fields = array(), $allow_redirects = true, $cert = NULL) |
||
| 625 | } |
||
| 626 | |||
| 627 | public static function patch($url, $fields = array(), $allow_redirects = true, $cert = NULL) |
||
| 628 | { |
||
| 629 | self::init (); |
||
| 630 | return self::request($url, 'PATCH', $fields, $allow_redirects, $cert); |
||
| 631 | } |
||
| 632 | |||
| 633 | /** |
||
| 634 | * request |
||
| 635 | * |
||
| 636 | * @param mixed $url 请求URL |
||
| 637 | * @param string $method 请求方法 |
||
| 638 | * @param array $fields 表单字段 |
||
| 639 | * @param array $files 上传文件 |
||
| 640 | * @param mixed $cert CA证书 |
||
| 641 | * @return void |
||
| 642 | * @author seatle <[email protected]> |
||
| 643 | * @created time :2017-08-03 18:06 |
||
| 644 | */ |
||
| 645 | public static function request($url, $method = 'GET', $fields = array(), $files = array(), $allow_redirects = true, $cert = NULL) |
||
| 646 | { |
||
| 647 | $method = strtoupper($method); |
||
| 648 | if(!self::_is_url($url)) |
||
| 649 | { |
||
| 650 | self::$error = "You have requested URL ({$url}) is not a valid HTTP address"; |
||
| 651 | return false; |
||
| 652 | } |
||
| 653 | |||
| 654 | // 如果是 get 方式,直接拼凑一个 url 出来 |
||
| 655 | if ($method == 'GET' && !empty($fields)) |
||
| 656 | { |
||
| 657 | $url = $url.(strpos($url, '?') === false ? '?' : '&').http_build_query($fields); |
||
| 658 | } |
||
| 659 | |||
| 660 | $parse_url = parse_url($url); |
||
| 661 | if (empty($parse_url) || empty($parse_url['host']) || !in_array($parse_url['scheme'], array('http', 'https'))) |
||
| 662 | { |
||
| 663 | self::$error = "No connection adapters were found for '{$url}'"; |
||
| 664 | return false; |
||
| 665 | } |
||
| 666 | $scheme = $parse_url['scheme']; |
||
| 667 | $domain = $parse_url['host']; |
||
| 668 | |||
| 669 | // 随机绑定 hosts,做负载均衡 |
||
| 670 | if (self::$hosts) |
||
| 671 | { |
||
| 672 | if (isset(self::$hosts[$domain])) |
||
| 673 | { |
||
| 674 | $hosts = self::$hosts[$domain]; |
||
| 675 | $key = rand(0, count($hosts)-1); |
||
| 676 | $ip = $hosts[$key]; |
||
| 677 | $url = str_replace($domain, $ip, $url); |
||
| 678 | self::$rawheaders['Host'] = $domain; |
||
| 679 | } |
||
| 680 | } |
||
| 681 | |||
| 682 | curl_setopt( self::$ch, CURLOPT_URL, $url ); |
||
| 683 | |||
| 684 | if ($method != 'GET') |
||
| 685 | { |
||
| 686 | // 如果是 post 方式 |
||
| 687 | if ($method == 'POST') |
||
| 688 | { |
||
| 689 | //curl_setopt( self::$ch, CURLOPT_POST, true ); |
||
| 690 | $tmpheaders = array_change_key_case(self::$rawheaders, CASE_LOWER); |
||
| 691 | // 有些RESTful服务只接受JSON形态的数据 |
||
| 692 | // CURLOPT_POST会把上傳的文件类型设为 multipart/form-data |
||
| 693 | // 把CURLOPT_POSTFIELDS的内容按multipart/form-data 的形式编码 |
||
| 694 | // CURLOPT_CUSTOMREQUEST可以按指定内容上传 |
||
| 695 | if ( isset($tmpheaders['content-type']) && $tmpheaders['content-type'] == 'application/json' ) |
||
| 696 | { |
||
| 697 | curl_setopt( self::$ch, CURLOPT_CUSTOMREQUEST, $method ); |
||
| 698 | } |
||
| 699 | else |
||
| 700 | { |
||
| 701 | curl_setopt( self::$ch, CURLOPT_POST, true ); |
||
| 702 | } |
||
| 703 | |||
| 704 | $file_fields = array(); |
||
| 705 | if (!empty($files)) |
||
| 706 | { |
||
| 707 | foreach ($files as $postname => $file) |
||
| 708 | { |
||
| 709 | $filepath = realpath($file); |
||
| 710 | // 如果文件不存在 |
||
| 711 | if (!file_exists($filepath)) |
||
| 712 | { |
||
| 713 | continue; |
||
| 714 | } |
||
| 715 | |||
| 716 | $filename = basename($filepath); |
||
| 717 | $type = self::get_mimetype($filepath); |
||
| 718 | $file_fields[$postname] = curl_file_create($filepath, $type, $filename); |
||
| 719 | // curl -F "name=seatle&file=@/absolute/path/to/image.png" htt://localhost/uploadfile.php |
||
| 720 | //$cfile = '@'.realpath($filename).";type=".$type.";filename=".$filename; |
||
| 721 | } |
||
| 722 | } |
||
| 723 | } |
||
| 724 | else |
||
| 725 | { |
||
| 726 | self::$rawheaders['X-HTTP-Method-Override'] = $method; |
||
| 727 | curl_setopt( self::$ch, CURLOPT_CUSTOMREQUEST, $method ); |
||
| 728 | } |
||
| 729 | |||
| 730 | if ( $method == 'POST' ) |
||
| 731 | { |
||
| 732 | // 不是上传文件的,用http_build_query, 能实现更好的兼容性,更小的请求数据包 |
||
| 733 | if ( empty($file_fields) ) |
||
| 734 | { |
||
| 735 | // post方式 |
||
| 736 | if ( is_array($fields) ) |
||
| 737 | { |
||
| 738 | $fields = http_build_query($fields); |
||
| 739 | } |
||
| 740 | } |
||
| 741 | else |
||
| 742 | { |
||
| 743 | // 有post数据 |
||
| 744 | if ( is_array($fields) && !empty($fields) ) |
||
| 745 | { |
||
| 746 | // 某些server可能会有问题 |
||
| 747 | $fields = array_merge($fields, $file_fields); |
||
| 748 | } |
||
| 749 | else |
||
| 750 | { |
||
| 751 | $fields = $file_fields; |
||
| 752 | } |
||
| 753 | } |
||
| 754 | |||
| 755 | // 不能直接传数组,不知道是什么Bug,会非常慢 |
||
| 756 | curl_setopt( self::$ch, CURLOPT_POSTFIELDS, $fields ); |
||
| 757 | } |
||
| 758 | } |
||
| 759 | |||
| 760 | $cookies = self::get_cookies(); |
||
| 761 | $domain_cookies = self::get_cookies($domain); |
||
| 762 | $cookies = array_merge($cookies, $domain_cookies); |
||
| 763 | // 是否设置了cookie |
||
| 764 | if (!empty($cookies)) |
||
| 765 | { |
||
| 766 | foreach ($cookies as $key=>$value) |
||
| 767 | { |
||
| 768 | $cookie_arr[] = $key.'='.$value; |
||
| 769 | } |
||
| 770 | $cookies = implode('; ', $cookie_arr); |
||
| 771 | curl_setopt(self::$ch, CURLOPT_COOKIE, $cookies); |
||
| 772 | } |
||
| 773 | |||
| 774 | if (!empty(self::$useragents)) |
||
| 775 | { |
||
| 776 | $key = rand(0, count(self::$useragents) - 1); |
||
| 777 | self::$rawheaders['User-Agent'] = self::$useragents[$key]; |
||
| 778 | } |
||
| 779 | |||
| 780 | if (!empty(self::$client_ips)) |
||
| 781 | { |
||
| 782 | $key = rand(0, count(self::$client_ips) - 1); |
||
| 783 | self::$rawheaders['CLIENT-IP'] = self::$client_ips[$key]; |
||
| 784 | self::$rawheaders['X-FORWARDED-FOR'] = self::$client_ips[$key]; |
||
| 785 | } |
||
| 786 | |||
| 787 | if (self::$rawheaders) |
||
| 788 | { |
||
| 789 | $http_headers = array(); |
||
| 790 | foreach (self::$rawheaders as $k=>$v) |
||
| 791 | { |
||
| 792 | $http_headers[] = $k.': '.$v; |
||
| 793 | } |
||
| 794 | curl_setopt( self::$ch, CURLOPT_HTTPHEADER, $http_headers ); |
||
| 795 | } |
||
| 796 | |||
| 797 | curl_setopt( self::$ch, CURLOPT_ENCODING, 'gzip' ); |
||
| 798 | |||
| 799 | // 关闭验证 |
||
| 800 | if ($scheme == 'https') |
||
| 801 | { |
||
| 802 | curl_setopt(self::$ch, CURLOPT_SSL_VERIFYPEER, false); |
||
| 803 | curl_setopt(self::$ch, CURLOPT_SSL_VERIFYHOST, false); |
||
| 804 | } |
||
| 805 | |||
| 806 | if (self::$proxies) |
||
| 807 | { |
||
| 808 | $key = rand(0, count(self::$proxies) - 1); |
||
| 809 | $proxy = self::$proxies[$key]; |
||
| 810 | curl_setopt( self::$ch, CURLOPT_PROXY, $proxy ); |
||
| 811 | } |
||
| 812 | |||
| 813 | // header + body,header 里面有 cookie |
||
| 814 | curl_setopt( self::$ch, CURLOPT_HEADER, true ); |
||
| 815 | // 请求跳转后的内容 |
||
| 816 | if ($allow_redirects) |
||
| 817 | { |
||
| 818 | curl_setopt( self::$ch, CURLOPT_FOLLOWLOCATION, true); |
||
| 819 | } |
||
| 820 | |||
| 821 | self::$raw = curl_exec ( self::$ch ); |
||
| 822 | // 真实url |
||
| 823 | //$location = curl_getinfo( self::$ch, CURLINFO_EFFECTIVE_URL); |
||
| 824 | self::$info = curl_getinfo( self::$ch ); |
||
| 825 | //print_r(self::$info); |
||
| 826 | self::$status_code = self::$info['http_code']; |
||
| 827 | if (self::$raw === false) |
||
| 828 | { |
||
| 829 | self::$error = 'Curl error: ' . curl_error( self::$ch ); |
||
| 830 | //trigger_error(self::$error, E_USER_WARNING); |
||
| 831 | } |
||
| 832 | |||
| 833 | // 关闭句柄 |
||
| 834 | curl_close( self::$ch ); |
||
| 835 | |||
| 836 | // 请求成功之后才把URL存起来 |
||
| 837 | list($header, $text) = self::split_header_body(); |
||
| 838 | self::$history = self::get_history($header); |
||
| 839 | self::$headers = self::get_response_headers($header); |
||
| 840 | self::get_response_cookies($header, $domain); |
||
| 841 | //$data = substr($data, 10); |
||
| 842 | //$data = gzinflate($data); |
||
| 843 | return $text; |
||
| 844 | } |
||
| 845 | |||
| 846 | public static function get_history($header) |
||
| 847 | { |
||
| 848 | $status_code = 0; |
||
| 849 | $lines = explode("\n", $header); |
||
| 850 | foreach ($lines as $line) |
||
| 851 | { |
||
| 852 | $line = trim($line); |
||
| 853 | if (preg_match("#^HTTP/.*? (\d+) Found#", $line, $out)) |
||
| 854 | { |
||
| 855 | $status_code = empty($out[1]) ? 0 : intval($out[1]); |
||
| 856 | } |
||
| 857 | } |
||
| 858 | return $status_code; |
||
| 859 | } |
||
| 860 | |||
| 861 | // 获取 mimetype |
||
| 862 | public static function get_mimetype($filepath) |
||
| 870 | } |
||
| 871 | |||
| 872 | /** |
||
| 873 | * 拼凑文件和表单 |
||
| 874 | * 占时没有用到 |
||
| 875 | * |
||
| 876 | * @param mixed $post_fields |
||
| 877 | * @param mixed $file_fields |
||
| 878 | * @return void |
||
| 879 | * @author seatle <[email protected]> |
||
| 880 | * @created time :2017-08-03 18:06 |
||
| 881 | */ |
||
| 882 | public static function get_postfile_form($post_fields, $file_fields) |
||
| 920 | } |
||
| 921 | |||
| 922 | /** |
||
| 923 | * html encoding transform |
||
| 924 | * |
||
| 925 | * @param string $html |
||
| 926 | * @param string $in |
||
| 927 | * @param string $out |
||
| 928 | * @param string $content |
||
| 929 | * @param string $mode |
||
| 930 | * auto|iconv|mb_convert_encoding |
||
| 931 | * @return string |
||
| 932 | */ |
||
| 933 | public static function encoding($html, $in = null, $out = null, $mode = 'auto') |
||
| 997 | } |
||
| 998 | } |
||
| 999 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths