HttpUtil.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <?php
  2. namespace loyalsoft;
  3. include_once 'IPQuery/IPQuery.php';
  4. /**
  5. * Http辅助类,可以发送请求/接收请求(提取参数)
  6. * @author gwang (email: mail@wanggangzero.cn)
  7. * @copyright 2016-3-12 ©SJZ LoyalSoft Corporation & gwang. All rights reserved.
  8. */
  9. class HttpUtil {
  10. /**
  11. * 从请求字符串中解析请求参数
  12. * @param type $queryStr
  13. * @return type 注意:解析过程未加入url_decode, 请调用方根据情况自行处理.
  14. */
  15. public static function parseQueryParas($queryStr) {
  16. // $queryStr = urldecode($queryStr);
  17. $arr = explode('&', $queryStr);
  18. $queryParas = array();
  19. foreach ($arr as $value) {
  20. $paras = explode('=', $value);
  21. $queryParas[$paras[0]] = isset($paras[1]) ? $paras[1] : "";
  22. }
  23. return $queryParas;
  24. }
  25. /**
  26. * 执行一个 HTTP 请求
  27. *
  28. * @param string $url 执行请求的URL
  29. * @param mixed $params 表单参数, 可以是array, 也可以是经过url编码之后的string
  30. * @param mixed $cookie cookie参数, 可以是array, 也可以是经过拼接的string, 默认array()
  31. * @param array $header http请求头, 默认array()
  32. * @param string $method 请求方法 post / get, 默认='post'
  33. * @param string $protocol http协议类型 http / https, 默认='http'
  34. * @return array 结果数组 {"result":bool,"msg":返回值/curlErrMsg,"errno":curl错误码,"ifno":curlInfo}
  35. */
  36. public static function makeRequest($url, $params, $cookie = array(), #
  37. $header = array(), $method = 'post', $protocol = 'https') {
  38. $query_string = self::makeQueryString($params);
  39. $cookie_string = self::makeCookieString($cookie);
  40. $ch = curl_init();
  41. if ('GET' == strtoupper($method)) { # Get
  42. curl_setopt($ch, CURLOPT_URL, "$url?$query_string");
  43. } else { # POST
  44. curl_setopt($ch, CURLOPT_URL, $url);
  45. curl_setopt($ch, CURLOPT_POST, 1);
  46. curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string); # postdata
  47. }
  48. curl_setopt($ch, CURLOPT_HEADER, false); # 控制是否返回响应头信息
  49. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  50. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3); # 超时时间
  51. // 如果客户端要发送一段很大的数据, 可以先向服务器发送一个expect: 100-continue,
  52. // 等待服务器响应 100以后, 继续发送数据体. 比如nginx默认接收客户端数据的大小为1M,PHP2M.
  53. if (strlen($query_string) > 1024 * 1024) {
  54. if (is_array($header)) { # http header是个数组,
  55. $header[] = 'Expect: 100-continue'; # 补充一个'Expect:', 避免出现 100-continue.
  56. } else if (is_string($header)) { # 如果header传过来了一个字符串
  57. $header = array($header, 'Expect: 100-continue'); # 拼接一个数组
  58. } else { # 其他情况,直接忽略, 覆盖掉
  59. $header = array('Expect: 100-continue');
  60. }
  61. }
  62. curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  63. if (!empty($cookie_string)) {
  64. curl_setopt($ch, CURLOPT_COOKIE, $cookie_string);
  65. }
  66. if ('https' == $protocol or substr($url, 0, 5) == 'https') { # 若为https协议
  67. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); # 若是出错,检查php.ini中curl.cainfo配置
  68. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  69. }
  70. // curl_setopt($ch, CURLOPT_PROXYPORT, 8888); # 代理,调试用的
  71. // curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1');
  72. $ret = curl_exec($ch);
  73. $err = curl_error($ch);
  74. if (false === $ret || !empty($err)) {
  75. $errno = curl_errno($ch);
  76. $info = curl_getinfo($ch);
  77. curl_close($ch);
  78. return array(
  79. 'result' => false,
  80. 'msg' => $err,
  81. 'errno' => $errno,
  82. 'info' => $info,
  83. );
  84. }
  85. curl_close($ch);
  86. return array(
  87. 'result' => true,
  88. 'msg' => $ret,
  89. );
  90. }
  91. /**
  92. * 从参数构造请求串
  93. * @param type $params 如果是字符串直接返回,(关联)数组或者object(仅取public字段)
  94. * @return string 编码规范-RFC3986
  95. */
  96. public static function makeQueryString($params) {
  97. if (is_string($params)) {
  98. return $params;
  99. }
  100. return http_build_query($params, "", '&', PHP_QUERY_RFC3986); # 3986
  101. }
  102. /**
  103. * 从参数构造Cookie字符串
  104. * @param type $params 如果是字符串直接返回,(关联)数组或者object(仅取public字段)
  105. * @return string 编码规范-RFC3986
  106. */
  107. public static function makeCookieString($params) {
  108. if (is_string($params)) {
  109. return $params;
  110. }
  111. return http_build_query($params, "", "; ", PHP_QUERY_RFC3986); # 3986
  112. }
  113. /**
  114. * 取Request过来的Data转为关联数组
  115. * @return array
  116. */
  117. public static function getQueryParas() {
  118. $param = $_REQUEST;
  119. if (isset($_SERVER['REQUEST_METHOD'])) {
  120. switch ($_SERVER['REQUEST_METHOD']) {
  121. case 'GET':
  122. $param = $_REQUEST;
  123. break;
  124. case 'POST':
  125. $str = file_get_contents('php://input'); # 注意: 若是multipart/form-data,则PHP不会填充input.
  126. $param = array_merge($param, ( strlen($str) > 0 ? self::parseQueryParas($str) : array()));
  127. break;
  128. default:
  129. }
  130. }
  131. return $param;
  132. }
  133. /**
  134. * 取Request过来的数据流转为字符串
  135. * @return string
  136. */
  137. public static function getQueryString() {
  138. $queryStr = null;
  139. if (isset($_SERVER['REQUEST_METHOD'])) {
  140. switch ($_SERVER['REQUEST_METHOD']) {
  141. case 'GET':
  142. $queryStr = $_SERVER['QUERY_STRING'];
  143. break;
  144. case 'POST':
  145. $queryStr = file_get_contents('php://input');
  146. break;
  147. default:
  148. }
  149. }
  150. return $queryStr;
  151. }
  152. /**
  153. * 用于确保服务器只响应POST方法.
  154. */
  155. public static function PostOnly() {
  156. if ($_SERVER['REQUEST_METHOD'] != 'POST') {
  157. header('Allow: POST ', false, 405);
  158. exit();
  159. }
  160. }
  161. /**
  162. * 测试是否支持tls1.2
  163. * @return bool true:支持, false:不支持
  164. */
  165. public static function CanSurpotTls_1_2() {
  166. $target_url = 'https://www.baidu.com/'; # 测试地址
  167. $ch = curl_init();
  168. curl_setopt($ch, CURLOPT_URL, $target_url);
  169. curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
  170. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  171. return curl_exec($ch) !== false; # 响应结果不为false则支持
  172. }
  173. /**
  174. * 获取客户端ip地址及端口
  175. * @return ip:port
  176. */
  177. public static function getClientEP() {
  178. return $_SERVER['REMOTE_ADDR'] . ":" . $_SERVER['REMOTE_PORT'];
  179. }
  180. /**
  181. * 获取客户端IP地址(摘自discuz)
  182. * @return string
  183. */
  184. public static function clientIP() {
  185. $ip = '未知IP';
  186. if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
  187. return self::is_ip($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : $ip;
  188. } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  189. return self::is_ip($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $ip;
  190. } elseif (!empty($_SERVER['REMOTE_ADDR'])) {
  191. return self::is_ip($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : $ip;
  192. } else {
  193. return $ip;
  194. }
  195. }
  196. /**
  197. * 获取ip的位置信息(中文)
  198. * @param type $ip
  199. * @return string
  200. */
  201. public static function IpInfo($ip) {
  202. $query = new \IPQuery();
  203. $info = $query->query($ip);
  204. return "{$info["pos"]}-{$info["isp"]}";
  205. }
  206. private static function is_ip($str) {
  207. $ip = explode('.', $str);
  208. for ($i = 0; $i < count($ip); $i++) {
  209. if ($ip[$i] > 255) {
  210. return false;
  211. }
  212. }
  213. return preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $str);
  214. }
  215. }
  216. /**
  217. * 取Request过来的Data转为关联数组
  218. * @return array
  219. */
  220. function query_paras() {
  221. return HttpUtil::getQueryParas();
  222. }
  223. /**
  224. * 取Request过来的数据流转为字符串
  225. * @return string
  226. */
  227. function query_string() {
  228. return HttpUtil::getQueryString();
  229. }