FeieHttpClient.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2017~2024 https://www.yiovo.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
  8. // +----------------------------------------------------------------------
  9. // | Author: 萤火科技 <admin@yiovo.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\common\library\printer\party;
  13. /**
  14. * 飞鹅云打印机API类
  15. * Class FeieHttpClient
  16. * @package app\common\library\printer\party
  17. */
  18. class FeieHttpClient
  19. {
  20. // Request vars
  21. var $host;
  22. var $port;
  23. var $path;
  24. var $method;
  25. var $postdata = '';
  26. var $cookies = [];
  27. var $referer;
  28. var $accept = 'text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,image/jpeg,image/gif,*/*';
  29. var $accept_encoding = 'gzip';
  30. var $accept_language = 'en-us';
  31. var $user_agent = 'Incutio HttpClient v0.9';
  32. var $timeout = 20;
  33. var $use_gzip = true;
  34. var $persist_cookies = true;
  35. var $persist_referers = true;
  36. var $debug = false;
  37. var $handle_redirects = true;
  38. var $max_redirects = 5;
  39. var $headers_only = false;
  40. var $username;
  41. var $password;
  42. var $status;
  43. var $headers = [];
  44. var $content = '';
  45. var $errormsg;
  46. var $redirect_count = 0;
  47. var $cookie_host = '';
  48. public function __construct($host, $port = 80)
  49. {
  50. $this->host = $host;
  51. $this->port = $port;
  52. }
  53. function get($path, $data = false)
  54. {
  55. $this->path = $path;
  56. $this->method = 'GET';
  57. if ($data) {
  58. $this->path .= '?' . $this->buildQueryString($data);
  59. }
  60. return $this->doRequest();
  61. }
  62. function post($path, $data)
  63. {
  64. $this->path = $path;
  65. $this->method = 'POST';
  66. $this->postdata = $this->buildQueryString($data);
  67. return $this->doRequest();
  68. }
  69. function buildQueryString($data)
  70. {
  71. $querystring = '';
  72. if (is_array($data)) {
  73. foreach ($data as $key => $val) {
  74. if (is_array($val)) {
  75. foreach ($val as $val2) {
  76. $querystring .= urlencode((string)$key) . '=' . urlencode((string)$val2) . '&';
  77. }
  78. } else {
  79. $querystring .= urlencode((string)$key) . '=' . urlencode((string)$val) . '&';
  80. }
  81. }
  82. $querystring = substr($querystring, 0, -1); // Eliminate unnecessary &
  83. } else {
  84. $querystring = $data;
  85. }
  86. return $querystring;
  87. }
  88. function doRequest()
  89. {
  90. if (!$fp = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout)) {
  91. switch ($errno) {
  92. case -3:
  93. $this->errormsg = 'Socket creation failed (-3)';
  94. break;
  95. case -4:
  96. $this->errormsg = 'DNS lookup failure (-4)';
  97. break;
  98. case -5:
  99. $this->errormsg = 'Connection refused or timed out (-5)';
  100. break;
  101. default:
  102. $this->errormsg = 'Connection failed (' . $errno . ')';
  103. $this->errormsg .= ' ' . $errstr;
  104. $this->debug($this->errormsg);
  105. }
  106. return false;
  107. }
  108. socket_set_timeout($fp, $this->timeout);
  109. $request = $this->buildRequest();
  110. $this->debug('Request', $request);
  111. fwrite($fp, $request);
  112. $this->headers = [];
  113. $this->content = '';
  114. $this->errormsg = '';
  115. $inHeaders = true;
  116. $atStart = true;
  117. while (!feof($fp)) {
  118. $line = fgets($fp, 4096);
  119. if ($atStart) {
  120. $atStart = false;
  121. if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/', $line, $m)) {
  122. $this->errormsg = "Status code line invalid: " . htmlentities($line);
  123. $this->debug($this->errormsg);
  124. return false;
  125. }
  126. // $http_version = $m[1];
  127. $this->status = $m[2];
  128. // $status_string = $m[3];
  129. $this->debug(trim($line));
  130. continue;
  131. }
  132. if ($inHeaders) {
  133. if (trim($line) == '') {
  134. $inHeaders = false;
  135. $this->debug('Received Headers', $this->headers);
  136. if ($this->headers_only) {
  137. break;
  138. }
  139. continue;
  140. }
  141. if (!preg_match('/([^:]+):\\s*(.*)/', $line, $m)) {
  142. continue;
  143. }
  144. $key = strtolower(trim($m[1]));
  145. $val = trim($m[2]);
  146. if (isset($this->headers[$key])) {
  147. if (is_array($this->headers[$key])) {
  148. $this->headers[$key][] = $val;
  149. } else {
  150. $this->headers[$key] = [$this->headers[$key], $val];
  151. }
  152. } else {
  153. $this->headers[$key] = $val;
  154. }
  155. continue;
  156. }
  157. $this->content .= $line;
  158. }
  159. fclose($fp);
  160. if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] == 'gzip') {
  161. $this->debug('Content is gzip encoded, unzipping it');
  162. $this->content = substr($this->content, 10);
  163. $this->content = gzinflate($this->content);
  164. }
  165. if ($this->persist_cookies && isset($this->headers['set-cookie']) && $this->host == $this->cookie_host) {
  166. $cookies = $this->headers['set-cookie'];
  167. if (!is_array($cookies)) {
  168. $cookies = [$cookies];
  169. }
  170. foreach ($cookies as $cookie) {
  171. if (preg_match('/([^=]+)=([^;]+);/', $cookie, $m)) {
  172. $this->cookies[$m[1]] = $m[2];
  173. }
  174. }
  175. $this->cookie_host = $this->host;
  176. }
  177. if ($this->persist_referers) {
  178. $this->debug('Persisting referer: ' . $this->getRequestURL());
  179. $this->referer = $this->getRequestURL();
  180. }
  181. if ($this->handle_redirects) {
  182. if (++$this->redirect_count >= $this->max_redirects) {
  183. $this->errormsg = 'Number of redirects exceeded maximum (' . $this->max_redirects . ')';
  184. $this->debug($this->errormsg);
  185. $this->redirect_count = 0;
  186. return false;
  187. }
  188. $location = isset($this->headers['location']) ? $this->headers['location'] : '';
  189. $uri = isset($this->headers['uri']) ? $this->headers['uri'] : '';
  190. if ($location || $uri) {
  191. $url = parse_url($location . $uri);
  192. return $this->get($url['path']);
  193. }
  194. }
  195. return true;
  196. }
  197. function buildRequest()
  198. {
  199. $headers = [];
  200. $headers[] = "{$this->method} {$this->path} HTTP/1.0";
  201. $headers[] = "Host: {$this->host}";
  202. $headers[] = "User-Agent: {$this->user_agent}";
  203. $headers[] = "Accept: {$this->accept}";
  204. if ($this->use_gzip) {
  205. $headers[] = "Accept-encoding: {$this->accept_encoding}";
  206. }
  207. $headers[] = "Accept-language: {$this->accept_language}";
  208. if ($this->referer) {
  209. $headers[] = "Referer: {$this->referer}";
  210. }
  211. if ($this->cookies) {
  212. $cookie = 'Cookie: ';
  213. foreach ($this->cookies as $key => $value) {
  214. $cookie .= "$key=$value; ";
  215. }
  216. $headers[] = $cookie;
  217. }
  218. if ($this->username && $this->password) {
  219. $headers[] = 'Authorization: BASIC ' . base64_encode($this->username . ':' . $this->password);
  220. }
  221. if ($this->postdata) {
  222. $headers[] = 'Content-Type: application/x-www-form-urlencoded';
  223. $headers[] = 'Content-Length: ' . strlen($this->postdata);
  224. }
  225. $request = implode("\r\n", $headers) . "\r\n\r\n" . $this->postdata;
  226. return $request;
  227. }
  228. function getStatus()
  229. {
  230. return $this->status;
  231. }
  232. function getContent()
  233. {
  234. return $this->content;
  235. }
  236. function getHeaders()
  237. {
  238. return $this->headers;
  239. }
  240. function getHeader($header)
  241. {
  242. $header = strtolower($header);
  243. if (isset($this->headers[$header])) {
  244. return $this->headers[$header];
  245. } else {
  246. return false;
  247. }
  248. }
  249. function getError()
  250. {
  251. return $this->errormsg;
  252. }
  253. function getCookies()
  254. {
  255. return $this->cookies;
  256. }
  257. function getRequestURL()
  258. {
  259. $url = 'http://' . $this->host;
  260. if ($this->port != 80) {
  261. $url .= ':' . $this->port;
  262. }
  263. $url .= $this->path;
  264. return $url;
  265. }
  266. function setUserAgent($string)
  267. {
  268. $this->user_agent = $string;
  269. }
  270. function setAuthorization($username, $password)
  271. {
  272. $this->username = $username;
  273. $this->password = $password;
  274. }
  275. function setCookies($array)
  276. {
  277. $this->cookies = $array;
  278. }
  279. function useGzip($boolean)
  280. {
  281. $this->use_gzip = $boolean;
  282. }
  283. function setPersistCookies($boolean)
  284. {
  285. $this->persist_cookies = $boolean;
  286. }
  287. function setPersistReferers($boolean)
  288. {
  289. $this->persist_referers = $boolean;
  290. }
  291. function setHandleRedirects($boolean)
  292. {
  293. $this->handle_redirects = $boolean;
  294. }
  295. function setMaxRedirects($num)
  296. {
  297. $this->max_redirects = $num;
  298. }
  299. function setHeadersOnly($boolean)
  300. {
  301. $this->headers_only = $boolean;
  302. }
  303. function setDebug($boolean)
  304. {
  305. $this->debug = $boolean;
  306. }
  307. function quickGet($url)
  308. {
  309. $bits = parse_url($url);
  310. $host = $bits['host'];
  311. $port = $bits['port'] ?? 80;
  312. $path = $bits['path'] ?? '/';
  313. if (isset($bits['query'])) {
  314. $path .= '?' . $bits['query'];
  315. }
  316. $client = new self($host, $port);
  317. if (!$client->get($path)) {
  318. return false;
  319. } else {
  320. return $client->getContent();
  321. }
  322. }
  323. function quickPost($url, $data)
  324. {
  325. $bits = parse_url($url);
  326. $host = $bits['host'];
  327. $port = $bits['port'] ?? 80;
  328. $path = $bits['path'] ?? '/';
  329. $client = new self($host, $port);
  330. if (!$client->post($path, $data)) {
  331. return false;
  332. } else {
  333. return $client->getContent();
  334. }
  335. }
  336. function debug($msg, $object = false)
  337. {
  338. if ($this->debug) {
  339. print '<div style="border: 1px solid red; padding: 0.5em; margin: 0.5em;"><strong>HttpClient Debug:</strong> ' . $msg;
  340. if ($object) {
  341. ob_start();
  342. print_r($object);
  343. $content = htmlentities(ob_get_contents());
  344. ob_end_clean();
  345. print '<pre>' . $content . '</pre>';
  346. }
  347. print '</div>';
  348. }
  349. }
  350. }