Ihttp.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <?php
  2. namespace App\Module;
  3. use Exception;
  4. @error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
  5. class Ihttp
  6. {
  7. public static function ihttp_request($url, $post = [], $extra = [], $timeout = 60, $retRaw = false, $isGb2312 = false) {
  8. $urlset = parse_url($url);
  9. if(empty($urlset['path'])) {
  10. $urlset['path'] = '/';
  11. }
  12. if(!empty($urlset['query'])) {
  13. $urlset['query'] = "?{$urlset['query']}";
  14. }
  15. if(empty($urlset['port'])) {
  16. $urlset['port'] = $urlset['scheme'] == 'https' ? '443' : '80';
  17. }
  18. if (Base::strExists($url, 'https://') && !extension_loaded('openssl')) {
  19. if (!extension_loaded("openssl")) {
  20. return Base::retError('请开启您PHP环境的openssl');
  21. }
  22. }
  23. if(function_exists('curl_init') && function_exists('curl_exec')) {
  24. $ch = curl_init();
  25. curl_setopt($ch, CURLOPT_URL, $urlset['scheme']. '://' .$urlset['host'].($urlset['port'] == '80' ? '' : ':'.$urlset['port']).$urlset['path'].$urlset['query']);
  26. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  27. curl_setopt($ch, CURLOPT_HEADER, 1);
  28. if($post) {
  29. if (is_array($post)) {
  30. $filepost = false;
  31. foreach ($post as $name => $value) {
  32. if (is_string($value) && substr($value, 0, 1) == '@') {
  33. $filepost = true;
  34. break;
  35. }
  36. }
  37. if (!$filepost) {
  38. $post = http_build_query($post);
  39. }
  40. }
  41. curl_setopt($ch, CURLOPT_POST, 1);
  42. curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
  43. }
  44. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
  45. curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
  46. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  47. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
  48. curl_setopt($ch, CURLOPT_SSLVERSION, 1);
  49. if (defined('CURL_SSLVERSION_TLSv1')) {
  50. curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
  51. }
  52. curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1');
  53. if (!empty($extra) && is_array($extra)) {
  54. $headers = array();
  55. foreach ($extra as $opt => $value) {
  56. if (Base::strExists($opt, 'CURLOPT_')) {
  57. curl_setopt($ch, constant($opt), $value);
  58. } elseif (is_numeric($opt)) {
  59. curl_setopt($ch, $opt, $value);
  60. } else {
  61. $headers[] = "{$opt}: {$value}";
  62. }
  63. }
  64. if(!empty($headers)) {
  65. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  66. }
  67. }
  68. $data = curl_exec($ch);
  69. //$status = curl_getinfo($ch);
  70. $errno = curl_errno($ch);
  71. $error = curl_error($ch);
  72. curl_close($ch);
  73. if($errno || empty($data)) {
  74. return Base::retError($error);
  75. } else {
  76. if ($isGb2312) {
  77. try { $data = iconv('GB2312', 'UTF-8', $data); }catch (Exception $e) { }
  78. }
  79. $response = self::ihttp_response_parse($data);
  80. if ($retRaw === true) {
  81. return Base::retSuccess($response['code'], $response);
  82. }
  83. return Base::retSuccess($response['code'], $response['content']);
  84. }
  85. }
  86. $method = empty($post) ? 'GET' : 'POST';
  87. $fdata = "{$method} {$urlset['path']}{$urlset['query']} HTTP/1.1\r\n";
  88. $fdata .= "Host: {$urlset['host']}\r\n";
  89. if(function_exists('gzdecode')) {
  90. $fdata .= "Accept-Encoding: gzip, deflate\r\n";
  91. }
  92. $fdata .= "Connection: close\r\n";
  93. if (!empty($extra) && is_array($extra)) {
  94. foreach ($extra as $opt => $value) {
  95. if (!Base::strExists($opt, 'CURLOPT_')) {
  96. $fdata .= "{$opt}: {$value}\r\n";
  97. }
  98. }
  99. }
  100. //$body = '';
  101. if ($post) {
  102. if (is_array($post)) {
  103. $body = http_build_query($post);
  104. } else {
  105. $body = urlencode((string)$post);
  106. }
  107. $fdata .= 'Content-Length: ' . strlen($body) . "\r\n\r\n{$body}";
  108. } else {
  109. $fdata .= "\r\n";
  110. }
  111. if($urlset['scheme'] == 'https') {
  112. $fp = fsockopen('ssl://' . $urlset['host'], $urlset['port'], $errno, $error);
  113. } else {
  114. $fp = fsockopen($urlset['host'], $urlset['port'], $errno, $error);
  115. }
  116. stream_set_blocking($fp, true);
  117. stream_set_timeout($fp, $timeout);
  118. if (!$fp) {
  119. return Base::retError( $error);
  120. } else {
  121. fwrite($fp, $fdata);
  122. $content = '';
  123. while (!feof($fp))
  124. $content .= fgets($fp, 512);
  125. fclose($fp);
  126. if ($isGb2312) {
  127. try { $content = iconv('GB2312', 'UTF-8', $content); }catch (Exception $e) { }
  128. }
  129. $response = self::ihttp_response_parse($content, true);
  130. if ($retRaw === true) {
  131. return Base::retSuccess($response['code'], $response);
  132. }
  133. return Base::retSuccess($response['code'], $response['content']);
  134. }
  135. }
  136. public static function ihttp_get($url) {
  137. return self::ihttp_request($url);
  138. }
  139. public static function ihttp_post($url, $data, $timeout = 60) {
  140. $headers = array('Content-Type' => 'application/x-www-form-urlencoded');
  141. return self::ihttp_request($url, $data, $headers, $timeout);
  142. }
  143. public static function ihttp_proxy($url, $post = [], $timeout = 20, $extra = []) {
  144. return self::ihttp_request($url, $post, $extra, $timeout);
  145. }
  146. private static function ihttp_response_parse($data, $chunked = false) {
  147. $rlt = array();
  148. $pos = strpos($data, "\r\n\r\n");
  149. if (Base::strExists(substr($data, 0, $pos), "Proxy-agent:")) {
  150. $data = substr($data, $pos + 4, strlen($data));
  151. $pos = strpos($data, "\r\n\r\n");
  152. }
  153. $split1[0] = substr($data, 0, $pos);
  154. $split1[1] = substr($data, $pos + 4, strlen($data));
  155. $split2 = explode("\r\n", $split1[0], 2);
  156. preg_match('/^(\S+) (\S+) (\S+)$/', $split2[0], $matches);
  157. $rlt['code'] = $matches[2];
  158. $rlt['status'] = $matches[3];
  159. $rlt['responseline'] = $split2[0];
  160. $header = explode("\r\n", $split2[1]);
  161. $isgzip = false;
  162. $ischunk = false;
  163. foreach ($header as $v) {
  164. $row = explode(':', $v);
  165. $key = trim($row[0]);
  166. $value = trim(substr($v, strlen($row[0]) + 1));
  167. if (is_array($rlt['headers'][$key])) {
  168. $rlt['headers'][$key][] = $value;
  169. } elseif (!empty($rlt['headers'][$key])) {
  170. $temp = $rlt['headers'][$key];
  171. unset($rlt['headers'][$key]);
  172. $rlt['headers'][$key][] = $temp;
  173. $rlt['headers'][$key][] = $value;
  174. } else {
  175. $rlt['headers'][$key] = $value;
  176. }
  177. if(!$isgzip && strtolower($key) == 'content-encoding' && strtolower($value) == 'gzip') {
  178. $isgzip = true;
  179. }
  180. if(!$ischunk && strtolower($key) == 'transfer-encoding' && strtolower($value) == 'chunked') {
  181. $ischunk = true;
  182. }
  183. }
  184. if($chunked && $ischunk) {
  185. $rlt['content'] = self::ihttp_response_parse_unchunk($split1[1]);
  186. } else {
  187. $rlt['content'] = $split1[1];
  188. }
  189. if($isgzip && function_exists('gzdecode')) {
  190. $rlt['content'] = gzdecode($rlt['content']);
  191. }
  192. $rlt['meta'] = $data;
  193. if($rlt['code'] == '100') {
  194. return self::ihttp_response_parse($rlt['content']);
  195. }
  196. return $rlt;
  197. }
  198. private static function ihttp_response_parse_unchunk($str = null) {
  199. if(!is_string($str) or strlen($str) < 1) {
  200. return false;
  201. }
  202. $eol = "\r\n";
  203. $add = strlen($eol);
  204. $tmp = $str;
  205. $str = '';
  206. do {
  207. $tmp = ltrim($tmp);
  208. $pos = strpos($tmp, $eol);
  209. if($pos === false) {
  210. return false;
  211. }
  212. $len = hexdec(substr($tmp, 0, $pos));
  213. if(!is_numeric($len) or $len < 0) {
  214. return false;
  215. }
  216. $str .= substr($tmp, ($pos + $add), $len);
  217. $tmp = substr($tmp, ($len + $pos + $add));
  218. $check = trim($tmp);
  219. } while(!empty($check));
  220. unset($tmp);
  221. return $str;
  222. }
  223. }