ProxyModule.class.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <?php
  2. /**
  3. * @name eolinker ams open source,eolinker开源版本
  4. * @link https://www.eolinker.com/
  5. * @package eolinker
  6. * @author www.eolinker.com 广州银云信息科技有限公司 ©2015-2018
  7. * eoLinker是目前全球领先、国内最大的在线API接口管理平台,提供自动生成API文档、API自动化测试、Mock测试、团队协作等功能,旨在解决由于前后端分离导致的开发效率低下问题。
  8. * 如在使用的过程中有任何问题,欢迎加入用户讨论群进行反馈,我们将会以最快的速度,最好的服务态度为您解决问题。
  9. *
  10. * eoLinker AMS开源版的开源协议遵循Apache License 2.0,如需获取最新的eolinker开源版以及相关资讯,请访问:https://www.eolinker.com/#/os/download
  11. *
  12. * 官方网站:https://www.eolinker.com/
  13. * 官方博客以及社区:http://blog.eolinker.com/
  14. * 使用教程以及帮助:http://help.eolinker.com/
  15. * 商务合作邮箱:market@eolinker.com
  16. * 用户讨论QQ群:284421832
  17. */
  18. class ProxyModule
  19. {
  20. /**
  21. * 转发请求到目的主机
  22. * @param string $method 请求方法
  23. * @param string $URL 请求路径
  24. * @param string $headers 请求头部
  25. * @param string $param 请求参数
  26. * @return bool|array
  27. */
  28. public function proxyToDesURL($method, $URL, &$headers = NULL, &$param = NULL)
  29. {
  30. //初始化请求
  31. $require = curl_init($URL);
  32. //判断是否HTTPS
  33. $isHttps = substr($URL, 0, 8) == "https://" ? TRUE : FALSE;
  34. //设置请求方式
  35. switch ($method) {
  36. case 'GET' :
  37. curl_setopt($require, CURLOPT_CUSTOMREQUEST, "GET");
  38. break;
  39. case 'POST' :
  40. {
  41. curl_setopt($require, CURLOPT_CUSTOMREQUEST, "POST");
  42. break;
  43. }
  44. case 'DELETE' :
  45. curl_setopt($require, CURLOPT_CUSTOMREQUEST, 'DELETE');
  46. break;
  47. case 'HEAD' :
  48. curl_setopt($require, CURLOPT_CUSTOMREQUEST, 'HEAD');
  49. //HEAD请求返回结果不包含BODY
  50. curl_setopt($require, CURLOPT_NOBODY, TRUE);
  51. break;
  52. case 'OPTIONS' :
  53. curl_setopt($require, CURLOPT_CUSTOMREQUEST, 'OPTIONS');
  54. break;
  55. case 'PATCH' :
  56. curl_setopt($require, CURLOPT_CUSTOMREQUEST, 'PATCH');
  57. break;
  58. case 'PUT' :
  59. curl_setopt($require, CURLOPT_CUSTOMREQUEST, 'PUT');
  60. break;
  61. default :
  62. return FALSE;
  63. }
  64. if ($param) {
  65. if (is_array($param)) {
  66. $str = '';
  67. foreach ($param as $key => $value) {
  68. $str .= $key . '=' . urlencode($value) . '&';
  69. }
  70. $param = substr($str, 0, -1);
  71. }
  72. curl_setopt($require, CURLOPT_POSTFIELDS, $param);
  73. }
  74. if ($isHttps) {
  75. //跳过证书检查
  76. curl_setopt($require, CURLOPT_SSL_VERIFYPEER, FALSE);
  77. //检查证书中是否设置域名
  78. curl_setopt($require, CURLOPT_SSL_VERIFYHOST, TRUE);
  79. }
  80. if ($headers) {
  81. //设置请求头
  82. curl_setopt($require, CURLOPT_HTTPHEADER, $headers);
  83. }
  84. //返回结果不直接输出
  85. curl_setopt($require, CURLOPT_RETURNTRANSFER, TRUE);
  86. //重定向
  87. //curl_setopt($require, CURLOPT_FOLLOWLOCATION, TRUE);
  88. //把返回头包含再输出中
  89. curl_setopt($require, CURLOPT_HEADER, TRUE);
  90. $time = date("Y-m-d H:i:s", time());
  91. //发送请求
  92. $response = $this->curl_redirect_exec($require);
  93. //获取返回结果状态码
  94. $httpCode = curl_getinfo($require, CURLINFO_HTTP_CODE);
  95. //获取传输总耗时
  96. $deny = curl_getinfo($require, CURLINFO_TOTAL_TIME) * 1000;
  97. //获取头部长度
  98. $headerSize = curl_getinfo($require, CURLINFO_HEADER_SIZE);
  99. if ($response) {
  100. //返回头部字符串
  101. $header = substr($response, 0, $headerSize);
  102. //返回体
  103. $body = substr($response, $headerSize);
  104. //过滤隐藏非法字符
  105. $bodyTemp = json_encode(array(0 => $body));
  106. $bodyTemp = str_replace('\ufeff', '', $bodyTemp);
  107. $bodyTemp = json_decode($bodyTemp, TRUE);
  108. $body = trim($bodyTemp[0]);
  109. //将返回结果头部转成数组
  110. $header_rows = array_filter(explode(PHP_EOL, $header), "trim");
  111. $respondHeaders = array();
  112. foreach ($header_rows as $row) {
  113. $keylen = strpos($row, ':');
  114. if ($keylen) {
  115. $respondHeaders[] = array(
  116. 'key' => substr($row, 0, $keylen),
  117. 'value' => trim(substr($row, $keylen + 1))
  118. );
  119. }
  120. }
  121. //关闭请求
  122. curl_close($require);
  123. return array(
  124. 'testTime' => $time,
  125. 'testDeny' => $deny,
  126. 'testHttpCode' => $httpCode,
  127. 'testResult' => array(
  128. 'headers' => $respondHeaders,
  129. 'body' => $body
  130. )
  131. );
  132. } else {
  133. if (curl_errno($require)) {
  134. $error = curl_error($require);
  135. //关闭请求
  136. curl_close($require);
  137. return array(
  138. 'testTime' => $time,
  139. 'testDeny' => $deny,
  140. 'testHttpCode' => 500,
  141. 'testResult' => array(
  142. 'headers' => array(),
  143. 'body' => $error)
  144. );
  145. }
  146. //关闭请求
  147. curl_close($require);
  148. return NULL;
  149. }
  150. }
  151. /**
  152. * 重定向处理
  153. * @param $ch
  154. * @return bool|mixed
  155. */
  156. private function curl_redirect_exec($ch)
  157. {
  158. static $curl_loops = 0;
  159. static $curl_max_loops = 20;
  160. if ($curl_loops++ >= $curl_max_loops) {
  161. $curl_loops = 0;
  162. return FALSE;
  163. }
  164. curl_setopt($ch, CURLOPT_HEADER, true);
  165. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  166. $response = curl_exec($ch);
  167. list($header,) = explode("\n\n", $response, 2);
  168. $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  169. if ($http_code == 301 || $http_code == 302) {
  170. $matches = array();
  171. preg_match('/Location:(.*?)\n/', $header, $matches);
  172. $url = @parse_url(trim(array_pop($matches)));
  173. if (!$url) {
  174. $curl_loops = 0;
  175. return $response;
  176. }
  177. $new_url = $url['scheme'] . '://' . $url['host'] . $url['path'] . ($url['query'] ? '?' . $url['query'] : '');
  178. if ($url['scheme'] == 'https') {
  179. //跳过证书检查
  180. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  181. //检查证书中是否设置域名
  182. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, TRUE);
  183. }
  184. curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
  185. curl_setopt($ch, CURLOPT_URL, $new_url);
  186. return $this->curl_redirect_exec($ch);
  187. } else {
  188. $curl_loops = 0;
  189. return $response;
  190. }
  191. }
  192. }
  193. ?>