<?php

namespace app\common;

use app\worm\ls\model\LSMatchErrorModel;
use think\facade\Env;
use think\facade\Log;

/**
* Class Http
*/
class Http
{
private static $info = [];

/**
* @param $url
* @param array $headers
* @param array $options
* @return \Requests_Response
*/
public static function get($url, array $headers = [], array $options = [])
{
$options = self::setOptions($options);
return self::call(__FUNCTION__, [$url, $headers, $options]);
}

/**
* @param $url
* @param array $headers
* @param array $options
* @return \Requests_Response
*/
public static function head($url, array $headers = [], array $options = [])
{
$options = self::setOptions($options);
return self::call(__FUNCTION__, [$url, $headers, $options]);
}

/**
* @param $url
* @param array $headers
* @param array $options
* @return \Requests_Response
*/
public static function delete($url, array $headers = [], array $options = [])
{
$options = self::setOptions($options);
return self::call(__FUNCTION__, [$url, $headers, $options]);
}

/**
* @param $url
* @param array $headers
* @param array $options
* @return \Requests_Response
*/
public static function trace($url, array $headers = [], array $options = [])
{
$options = self::setOptions($options);
return self::call(__FUNCTION__, [$url, $headers, $options]);
}

/**
* @param $url
* @param array $headers
* @param array $data
* @param array $options
* @return \Requests_Response
*/
public static function post($url, array $headers = [], $data = [], array $options = [])
{
$options = self::setOptions($options);
return self::call(__FUNCTION__, [$url, $headers, $data, $options]);
}

/**
* @param $url
* @param array $headers
* @param array $data
* @param array $options
* @return \Requests_Response
*/
public static function put($url, array $headers = [], array $data = [], array $options = [])
{
$options = self::setOptions($options);
return self::call(__FUNCTION__, [$url, $headers, $data, $options]);
}

/**
* @param $url
* @param array $headers
* @param array $data
* @param array $options
* @return \Requests_Response
*/
public static function options($url, array $headers = [], array $data = [], array $options = [])
{
$options = self::setOptions($options);
return self::call(__FUNCTION__, [$url, $headers, $data, $options]);
}

/**
* @param $url
* @param $headers
* @param array $data
* @param array $options
* @return \Requests_Response
*/
public static function patch($url, array $headers, array $data = [], array $options = [])
{
$options = self::setOptions($options);
return self::call(__FUNCTION__, [$url, $headers, $data, $options]);
}

/**
* @param string $url
* @param array $headers
* @param array $data
* @param string $type
* @param array $options
* @return \Requests_Response
*/
public static function request($url, array $headers = [], array $data = [], $type = \Requests::GET, array $options = [])
{
$options = self::setOptions($options);
return self::call(__FUNCTION__, [$url, $headers, $data, $type, $options]);
}

private static function getHooks()
{
$hooks = new \Requests_Hooks();
$hooks->register('curl.after_request', function ($headers, $info) {
self::$info = !is_array($info) ? [$info] : $info;
});

return $hooks;
}

private static function setOptions($options)
{
if (!isset($options['hooks'])) {
$options['hooks'] = self::getHooks();
}
$options['idn'] = false;
return $options;
}

private static function call($name, $args)
{
try {
$type = $name;

if ('request' === $name) {
$type = isset($args[3]) ? $args[3] : $name;
}

$type = strtolower($type);
$startTime = microtime(true);

//设置url
if ($type !== 'request_multiple') {
$args[0] = new RequestsIRI($args[0]);
}
$args[4]['verify'] = false;
$response = call_user_func_array(['Requests', $name], $args);
if ($response instanceof \Requests_Response && is_object($response->url)) {
$response->url = $response->url->uri;
}

return $response;
} catch (\Exception $e) {
Log::error($e->getMessage());
$response = new \Requests_Response();
$response->body = '';

return $response;
}
}

public function getProxyIp($force = false)
{
try {
$url = 'http://dps.kdlapi.com/api/getdps/?orderid=927181368146275&num=1&pt=1&sep=1';
$result = file_get_contents($url);
if (empty($result)) {
throw new \Exception('获取代理IP错误');
}

$result = explode(':', $result);
$ip = $result[0];
$port = $result[1];

$currentProxyIp = [
'ip' => $ip,
'port' => $port,
'time' => time()
];

return $currentProxyIp;
} catch (\Exception $e) {
\Log::error($e->getMessage());
return [];
}
}

//get请求快代理ip
public function doGetByKuaidailiIp($url, $headers = [])
{
try {
$ch = curl_init();
$tunnelhost = Env::get('kuaidailiip.tunnelhost');
$tunnelport = Env::get('kuaidailiip.tunnelport');
$proxy = $tunnelhost . ":" . $tunnelport;

//隧道用户名密码
$username = Env::get('kuaidailiip.username');
$password = Env::get('kuaidailiip.password');

//$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

//设置代理
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
//设置代理用户名密码
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$username}:{$password}");

//自定义header
if ($headers) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}

//自定义cookie
curl_setopt($ch, CURLOPT_COOKIE, '');
//使用gzip压缩传输数据让访问更快
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);

//返回response头部信息
// curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
//$info = curl_getinfo($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$err = curl_error($ch);
curl_close($ch);

if ($err && !$response) {
if ($httpCode == 407) {
throw new \Exception($url . '//doGetByKuaidailiIp代理IP出现错误(说明:1. 没有带上用户名密码验证2. 用户名密码错误,验证失败)' . $err);
} else if ($httpCode == 503) {
throw new \Exception($url . '//doGetByKuaidailiIp代理IP出现错误(说明:隧道转发代理IP错误)' . $err);
} else if ($httpCode == 403) {
throw new \Exception($url . '//doGetByKuaidailiIp代理IP出现错误(说明:Over Max Connection超过最大并发连接数,Access Forbidden禁止访问该网站)' . $err);
}
return false;
}

return $response;
} catch (\Exception $e) {
Log::error($e);
return '';
}
}

//post请求快代理ip
public function doPostByKuaidailiIp($url, $headers = [])
{
try {
$ch = curl_init();
$tunnelhost = Env::get('kuaidailiip.tunnelhost');
$tunnelport = Env::get('kuaidailiip.tunnelport');
$proxy = $tunnelhost . ":" . $tunnelport;

//隧道用户名密码
$username = Env::get('kuaidailiip.username');
$password = Env::get('kuaidailiip.password');

//$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);

//发送post请求
$requestData["post"] = "send post request";
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($requestData));

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

//设置代理
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
//设置代理用户名密码
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$username}:{$password}");

//自定义header
if ($headers) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}

//自定义cookie
curl_setopt($ch, CURLOPT_COOKIE, '');
//使用gzip压缩传输数据让访问更快
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);

//返回response头部信息
// curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$err = curl_error($ch);
//$info = curl_getinfo($ch);
curl_close($ch);

if ($err && !$response) {
//关闭资源
// throw new \Exception($url . '//doGetByKuaidailiIp代理IP出现错误' . $err);
return false;
}

return $response;
} catch (\Exception $e) {
\Log::error($e);
return '';
}
}

public function doGet($url, $headers = [], $options = [])
{
try {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_TIMEOUT => 10,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_SSL_VERIFYPEER => 0, // 对认证证书来源的检查
CURLOPT_SSL_VERIFYHOST => 0,
]);

if ($headers) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}

$forceGetIp = isset($options['forceGetIp']) && $options['forceGetIp'] ? true : false;

if ($forceGetIp && (config("app_env") != 'local')) {
$proxyInfo = $this->getProxyIp($forceGetIp);
$ip = empty($proxyInfo['ip']) ? '' : $proxyInfo['ip'];
$port = empty($proxyInfo['port']) ? '' : $proxyInfo['port'];
if (empty($ip) || empty($port)) {
throw new \Exception('获取代理IP失败');
}

curl_setopt($ch, CURLOPT_PROXY, $ip);
curl_setopt($ch, CURLOPT_PROXYPORT, $port);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); //使用http代理模式
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); //代理认证模式
}

if (isset($options['gzip']) && $options['gzip']) {
curl_setopt($ch, CURLOPT_ENCODING, "gzip");
}

$response = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);

if ($err) {
throw new \Exception('出现错误' . $err);
}

return $response;
} catch (\Exception $e) {
if (!empty($options['disabled_log'])) {
return '';
}
\Log::error($e);
return '';
}
}

public function doPost($url, $headers = [], $data = [])
{
try {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_TIMEOUT => 30,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => 1,
CURLOPT_ENCODING => "",
CURLOPT_SSL_VERIFYPEER => 0, // 对认证证书来源的检查
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_POSTFIELDS => $data
]);

if ($headers) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}

$response = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);

if ($err) {
throw new \Exception('出现错误' . $err);
}

return $response;
} catch (\Exception $e) {
\Log::error($e->getMessage());
return '';
}
}
}