HproseHttpClient.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. <?php
  2. /**********************************************************\
  3. | |
  4. | hprose |
  5. | |
  6. | Official WebSite: http://www.hprose.com/ |
  7. | http://www.hprose.net/ |
  8. | http://www.hprose.org/ |
  9. | |
  10. \**********************************************************/
  11. /**********************************************************\
  12. * *
  13. * HproseHttpClient.php *
  14. * *
  15. * hprose http client library for php5. *
  16. * *
  17. * LastModified: Nov 12, 2013 *
  18. * Author: Ma Bingyao <andot@hprfc.com> *
  19. * *
  20. \**********************************************************/
  21. require_once('HproseCommon.php');
  22. require_once('HproseIO.php');
  23. require_once('HproseClient.php');
  24. abstract class HproseBaseHttpClient extends HproseClient {
  25. protected $host;
  26. protected $path;
  27. protected $secure;
  28. protected $proxy;
  29. protected $header;
  30. protected $timeout;
  31. protected $keepAlive;
  32. protected $keepAliveTimeout;
  33. protected static $cookieManager = array();
  34. static function hproseKeepCookieInSession() {
  35. $_SESSION['HPROSE_COOKIE_MANAGER'] = self::$cookieManager;
  36. }
  37. public static function keepSession() {
  38. if (array_key_exists('HPROSE_COOKIE_MANAGER', $_SESSION)) {
  39. self::$cookieManager = $_SESSION['HPROSE_COOKIE_MANAGER'];
  40. }
  41. register_shutdown_function(array('HproseBaseHttpClient', 'hproseKeepCookieInSession'));
  42. }
  43. protected function setCookie($headers) {
  44. foreach ($headers as $header) {
  45. @list($name, $value) = explode(':', $header, 2);
  46. if (strtolower($name) == 'set-cookie' ||
  47. strtolower($name) == 'set-cookie2') {
  48. $cookies = explode(';', trim($value));
  49. $cookie = array();
  50. list($name, $value) = explode('=', trim($cookies[0]), 2);
  51. $cookie['name'] = $name;
  52. $cookie['value'] = $value;
  53. for ($i = 1; $i < count($cookies); $i++) {
  54. list($name, $value) = explode('=', trim($cookies[$i]), 2);
  55. $cookie[strtoupper($name)] = $value;
  56. }
  57. // Tomcat can return SetCookie2 with path wrapped in "
  58. if (array_key_exists('PATH', $cookie)) {
  59. $cookie['PATH'] = trim($cookie['PATH'], '"');
  60. }
  61. else {
  62. $cookie['PATH'] = '/';
  63. }
  64. if (array_key_exists('EXPIRES', $cookie)) {
  65. $cookie['EXPIRES'] = strtotime($cookie['EXPIRES']);
  66. }
  67. if (array_key_exists('DOMAIN', $cookie)) {
  68. $cookie['DOMAIN'] = strtolower($cookie['DOMAIN']);
  69. }
  70. else {
  71. $cookie['DOMAIN'] = $this->host;
  72. }
  73. $cookie['SECURE'] = array_key_exists('SECURE', $cookie);
  74. if (!array_key_exists($cookie['DOMAIN'], self::$cookieManager)) {
  75. self::$cookieManager[$cookie['DOMAIN']] = array();
  76. }
  77. self::$cookieManager[$cookie['DOMAIN']][$cookie['name']] = $cookie;
  78. }
  79. }
  80. }
  81. protected abstract function formatCookie($cookies);
  82. protected function getCookie() {
  83. $cookies = array();
  84. foreach (self::$cookieManager as $domain => $cookieList) {
  85. if (strpos($this->host, $domain) !== false) {
  86. $names = array();
  87. foreach ($cookieList as $cookie) {
  88. if (array_key_exists('EXPIRES', $cookie) && (time() > $cookie['EXPIRES'])) {
  89. $names[] = $cookie['name'];
  90. }
  91. elseif (strpos($this->path, $cookie['PATH']) === 0) {
  92. if ((($this->secure && $cookie['SECURE']) ||
  93. !$cookie['SECURE']) && !is_null($cookie['value'])) {
  94. $cookies[] = $cookie['name'] . '=' . $cookie['value'];
  95. }
  96. }
  97. }
  98. foreach ($names as $name) {
  99. unset(self::$cookieManager[$domain][$name]);
  100. }
  101. }
  102. }
  103. return $this->formatCookie($cookies);
  104. }
  105. public function __construct($url = '') {
  106. parent::__construct($url);
  107. $this->header = array('Content-type' => 'application/hprose');
  108. }
  109. public function useService($url = '', $namespace = '') {
  110. $serviceProxy = parent::useService($url, $namespace);
  111. if ($url) {
  112. $url = parse_url($url);
  113. $this->secure = (strtolower($url['scheme']) == 'https');
  114. $this->host = strtolower($url['host']);
  115. $this->path = $url['path'];
  116. $this->timeout = 30000;
  117. $this->keepAlive = false;
  118. $this->keepAliveTimeout = 300;
  119. }
  120. return $serviceProxy;
  121. }
  122. public function setHeader($name, $value) {
  123. $lname = strtolower($name);
  124. if ($lname != 'content-type' &&
  125. $lname != 'content-length' &&
  126. $lname != 'host') {
  127. if ($value) {
  128. $this->header[$name] = $value;
  129. }
  130. else {
  131. unset($this->header[$name]);
  132. }
  133. }
  134. }
  135. public function setProxy($proxy = NULL) {
  136. $this->proxy = $proxy;
  137. }
  138. public function setTimeout($timeout) {
  139. $this->timeout = $timeout;
  140. }
  141. public function getTimeout() {
  142. return $this->timeout;
  143. }
  144. public function setKeepAlive($keepAlive = true) {
  145. $this->keepAlive = $keepAlive;
  146. }
  147. public function getKeepAlive() {
  148. return $this->keeepAlive;
  149. }
  150. public function setKeepAliveTimeout($timeout) {
  151. $this->keepAliveTimeout = $timeout;
  152. }
  153. public function getKeepAliveTimeout() {
  154. return $this->keepAliveTimeout;
  155. }
  156. }
  157. if (class_exists('SaeFetchurl')) {
  158. class HproseHttpClient extends HproseBaseHttpClient {
  159. protected function formatCookie($cookies) {
  160. if (count($cookies) > 0) {
  161. return implode('; ', $cookies);
  162. }
  163. return '';
  164. }
  165. protected function send($request) {
  166. $f = new SaeFetchurl();
  167. $cookie = $this->getCookie();
  168. if ($cookie != '') {
  169. $f->setHeader("Cookie", $cookie);
  170. }
  171. if ($this->keepAlive) {
  172. $f->setHeader("Connection", "keep-alive");
  173. $f->setHeader("Keep-Alive", $this->keepAliveTimeout);
  174. }
  175. else {
  176. $f->setHeader("Connection", "close");
  177. }
  178. foreach ($this->header as $name => $value) {
  179. $f->setHeader($name, $value);
  180. }
  181. $f->setMethod("post");
  182. $f->setPostData($request);
  183. $f->setConnectTimeout($this->timeout);
  184. $f->setSendTimeout($this->timeout);
  185. $f->setReadTimeout($this->timeout);
  186. $response = $f->fetch($this->url);
  187. if ($f->errno()) {
  188. throw new HproseException($f->errno() . ": " . $f->errmsg());
  189. }
  190. $http_response_header = $f->responseHeaders(false);
  191. $this->setCookie($http_response_header);
  192. return $response;
  193. }
  194. }
  195. }
  196. elseif (function_exists('curl_init')) {
  197. class HproseHttpClient extends HproseBaseHttpClient {
  198. private $curl;
  199. protected function formatCookie($cookies) {
  200. if (count($cookies) > 0) {
  201. return "Cookie: " . implode('; ', $cookies);
  202. }
  203. return '';
  204. }
  205. public function __construct($url = '') {
  206. parent::__construct($url);
  207. $this->curl = curl_init();
  208. }
  209. protected function send($request) {
  210. curl_setopt($this->curl, CURLOPT_URL, $this->url);
  211. curl_setopt($this->curl, CURLOPT_HEADER, TRUE);
  212. curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, FALSE);
  213. curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, TRUE);
  214. curl_setopt($this->curl, CURLOPT_POST, TRUE);
  215. curl_setopt($this->curl, CURLOPT_POSTFIELDS, $request);
  216. $headers_array = array($this->getCookie(),
  217. "Content-Length: " . strlen($request));
  218. if ($this->keepAlive) {
  219. $headers_array[] = "Connection: keep-alive";
  220. $headers_array[] = "Keep-Alive: " . $this->keepAliveTimeout;
  221. }
  222. else {
  223. $headers_array[] = "Connection: close";
  224. }
  225. foreach ($this->header as $name => $value) {
  226. $headers_array[] = $name . ": " . $value;
  227. }
  228. curl_setopt($this->curl, CURLOPT_HTTPHEADER, $headers_array);
  229. if ($this->proxy) {
  230. curl_setopt($this->curl, CURLOPT_PROXY, $this->proxy);
  231. }
  232. if (defined(CURLOPT_TIMEOUT_MS)) {
  233. curl_setopt($this->curl, CURLOPT_TIMEOUT_MS, $this->timeout);
  234. }
  235. else {
  236. curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout / 1000);
  237. }
  238. $response = curl_exec($this->curl);
  239. $errno = curl_errno($this->curl);
  240. if ($errno) {
  241. throw new HproseException($errno . ": " . curl_error($this->curl));
  242. }
  243. do {
  244. list($response_headers, $response) = explode("\r\n\r\n", $response, 2);
  245. $http_response_header = explode("\r\n", $response_headers);
  246. $http_response_firstline = array_shift($http_response_header);
  247. if (preg_match('@^HTTP/[0-9]\.[0-9]\s([0-9]{3})\s(.*)@',
  248. $http_response_firstline, $matches)) {
  249. $response_code = $matches[1];
  250. $response_status = trim($matches[2]);
  251. }
  252. else {
  253. $response_code = "500";
  254. $response_status = "Unknown Error.";
  255. }
  256. } while (substr($response_code, 0, 1) == "1");
  257. if ($response_code != '200') {
  258. throw new HproseException($response_code . ": " . $response_status);
  259. }
  260. $this->setCookie($http_response_header);
  261. return $response;
  262. }
  263. public function __destruct() {
  264. curl_close($this->curl);
  265. }
  266. }
  267. }
  268. else {
  269. class HproseHttpClient extends HproseBaseHttpClient {
  270. protected function formatCookie($cookies) {
  271. if (count($cookies) > 0) {
  272. return "Cookie: " . implode('; ', $cookies) . "\r\n";
  273. }
  274. return '';
  275. }
  276. public function __errorHandler($errno, $errstr, $errfile, $errline) {
  277. throw new Exception($errstr, $errno);
  278. }
  279. protected function send($request) {
  280. $opts = array (
  281. 'http' => array (
  282. 'method' => 'POST',
  283. 'header'=> $this->getCookie() .
  284. "Content-Length: " . strlen($request) . "\r\n" .
  285. ($this->keepAlive ?
  286. "Connection: keep-alive\r\n" .
  287. "Keep-Alive: " . $this->keepAliveTimeout . "\r\n" :
  288. "Connection: close\r\n"),
  289. 'content' => $request,
  290. 'timeout' => $this->timeout / 1000.0,
  291. ),
  292. );
  293. foreach ($this->header as $name => $value) {
  294. $opts['http']['header'] .= "$name: $value\r\n";
  295. }
  296. if ($this->proxy) {
  297. $opts['http']['proxy'] = $this->proxy;
  298. $opts['http']['request_fulluri'] = true;
  299. }
  300. $context = stream_context_create($opts);
  301. set_error_handler(array(&$this, '__errorHandler'));
  302. $response = file_get_contents($this->url, false, $context);
  303. restore_error_handler();
  304. $this->setCookie($http_response_header);
  305. return $response;
  306. }
  307. }
  308. }
  309. ?>