HTTP_Request.php 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PEAR :: Cache |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1997-2003 The PHP Group |
  6. // +----------------------------------------------------------------------+
  7. // | This source file is subject to version 2.0 of the PHP license, |
  8. // | that is bundled with this package in the file LICENSE, and is |
  9. // | available at through the world-wide-web at |
  10. // | http://www.php.net/license/2_02.txt. |
  11. // | If you did not receive a copy of the PHP license and are unable to |
  12. // | obtain it through the world-wide-web, please send a note to |
  13. // | license@php.net so we can mail you a copy immediately. |
  14. // +----------------------------------------------------------------------+
  15. // | Authors: Fabien MARTY <fabien.marty@free.fr> |
  16. // +----------------------------------------------------------------------+
  17. //
  18. // $Id: HTTP_Request.php,v 1.8 2003/01/04 11:54:45 mj Exp $
  19. require_once 'Cache.php';
  20. require_once 'HTTP/Request.php';
  21. define('CACHE_HTTP_REQUEST_GROUP_NAME', 'cache_http_request');
  22. define('CACHE_HTTP_REQUEST_SUCCESS_RESPONSE_CODE', 200);
  23. define('CACHE_HTTP_REQUEST_KEEP_LOCAL_COPY', 1);
  24. define('CACHE_HTTP_REQUEST_RETURN_FALSE', 2);
  25. define('CACHE_HTTP_REQUEST_RETURN_PEAR_ERROR', 3);
  26. /**
  27. * HTTP_Request Cache
  28. *
  29. * The classical example is :
  30. *
  31. * You want to get news from another site through RSS remote files. But you
  32. * don't want to access to to the remote site at every time you display
  33. * its news on your site. Because, if the remote site is down or slow...
  34. * So you you need a class which makes a local cache copy of the remote file.
  35. * Every x hours, the cache is updated. But if the remote site is down, the
  36. * local cache copy is keeped (you can also get error messages if you want).
  37. *
  38. * So you need this class!
  39. *
  40. * Cache_HTTP_Request inherits from Cache and use HTTP_Request to access to
  41. * the remote file.
  42. *
  43. * Usage example :
  44. *
  45. * <?php
  46. * require_once('Cache/HTTP_Request.php');
  47. *
  48. * $cache = &new Cache_HTTP_Request('http://www.php.net', NULL, 'file', NULL, 3600);
  49. * $cache->sendRequest();
  50. * $remoteFileBody = $cache->getResponseBody();
  51. *
  52. * (...)
  53. * ?>
  54. *
  55. * @author Fabien MARTY <fabien.marty@free.fr>
  56. * @version $Id: HTTP_Request.php,v 1.8 2003/01/04 11:54:45 mj Exp $
  57. * @package Cache
  58. */
  59. class Cache_HTTP_Request extends Cache
  60. {
  61. // --- Private properties ---
  62. /**
  63. * Lifetime in seconds (0 endless)
  64. *
  65. * @var int $_expires
  66. */
  67. var $_expires;
  68. /**
  69. * HTTP Request
  70. *
  71. * @var object $_request
  72. */
  73. var $_request;
  74. /**
  75. * Cache id for the classic cache file
  76. *
  77. * @see sendRequest()
  78. * @var string $_id
  79. */
  80. var $_id;
  81. /**
  82. * Cache id for the endless cache file
  83. *
  84. * @see sendRequest()
  85. * @var string $_id
  86. */
  87. var $_id2;
  88. /**
  89. * Data to use
  90. *
  91. * @see getReponseBody(), getReponseHeader(), getReponseCode()
  92. * @var array $_data
  93. */
  94. var $_data ;
  95. // --- Public methods ---
  96. /**
  97. * Constructor
  98. *
  99. * @param $url The url to access
  100. * @param $params Associative array of parameters which can be:
  101. * method - Method to use, GET, POST etc
  102. * http - HTTP Version to use, 1.0 or 1.1
  103. * user - Basic Auth username
  104. * pass - Basic Auth password
  105. * proxy_host - Proxy server host
  106. * proxy_port - Proxy server port
  107. * proxy_user - Proxy auth username
  108. * proxy_pass - Proxy auth password
  109. * @param string $container Name of container class
  110. * @param array $containerOptions Array with container class options
  111. * @param int $mode What to do when the remote server is down :
  112. * CACHE_HTTP_REQUEST_KEEP_LOCAL_COPY or
  113. * CACHE_HTTP_REQUEST_RETURN_FALSE or
  114. * CACHE_HTTP_REQUEST_RETURN_PEAR_ERROR
  115. * @param int $expires lifetime of the cached data in seconds - 0 for endless
  116. * @see Cache, HTTP_Request
  117. * @access public
  118. */
  119. function Cache_HTTP_Request($url, $params = NULL, $container = 'file',
  120. $containerOptions = NULL, $expires = 3600,
  121. $mode = CACHE_HTTP_REQUEST_KEEP_LOCAL_COPY)
  122. {
  123. if (!isset($params)) $params = array();
  124. if (!isset($containerOptions)) {
  125. $containerOptions = array (
  126. 'cache_dir' => '/tmp/',
  127. 'filename_prefix' => 'cache_'
  128. );
  129. }
  130. $this->Cache($container, $containerOptions);
  131. $this->_request = &new HTTP_Request($url, $params);
  132. $this->_id = md5($url.serialize($params));
  133. $this->_id2 = md5($this->id); // we need two keys
  134. $this->_mode = $mode;
  135. $this->_expires = $expires;
  136. }
  137. /**
  138. * Deconstructor
  139. *
  140. * @access public
  141. */
  142. function _Cache_HTTP_Request()
  143. {
  144. $this->_Cache();
  145. }
  146. /**
  147. * Get and return the response body (NULL if no data available)
  148. *
  149. * @see sendRequest()
  150. * @return mixed response body
  151. * @access public
  152. */
  153. function getResponseBody()
  154. {
  155. return $this->_data['body'];
  156. }
  157. /**
  158. * Get and return the response code (NULL if no data available)
  159. *
  160. * @see sendRequest()
  161. * @return mixed response code
  162. * @access public
  163. */
  164. function getResponseCode()
  165. {
  166. return $this->_data['code'];
  167. }
  168. /**
  169. * Get and return the response header (NULL if no data available)
  170. *
  171. * @see sendRequest()
  172. * @return mixed response header
  173. * @access public
  174. */
  175. function getResponseHeader()
  176. {
  177. return $this->_data['header'];
  178. }
  179. /**
  180. * Set a new mode when the server is down
  181. *
  182. * @param int $newMode What to do when the remote server is down :
  183. * CACHE_HTTP_REQUEST_KEEP_LOCAL_COPY or
  184. * CACHE_HTTP_REQUEST_RETURN_FALSE or
  185. * CACHE_HTTP_REQUEST_RETURN_PEAR_ERROR
  186. * @access public
  187. */
  188. function setMode($newMode)
  189. {
  190. $this->_mode = $newMode;
  191. }
  192. /**
  193. * Send the HTTP request or use the cache system
  194. *
  195. * If there is a cache file for this HTTP request, the request is not re-sent.
  196. * Cached response is used. Yet, if the cache is expired, the HTTP request
  197. * is re-sent. Then, if the remote server is down, this method will return :
  198. * (depending on the selected mode)
  199. * - false or
  200. * - a PEAR_Error or (better)
  201. * - true and the local copy of the latest valid response will be used.
  202. *
  203. * (technical)
  204. * For the last choice, there is a technical tips.
  205. * Indeed, there are two cache files. The first one (id key) is a classical one
  206. * with the given lifetime. But it can be removed by automatic garbage collection
  207. * for example. So to be able to use the latest valid response (when the remote
  208. * server is dead), we make a second cache file with no lifetime (id2 key).
  209. *
  210. * @return mixed true or false or a PEAR_ERROR
  211. * @access public
  212. */
  213. function sendRequest()
  214. {
  215. if ($data = $this->get($this->_id, CACHE_HTTP_REQUEST_GROUP_NAME)) {
  216. // --- Cache hit ---
  217. $this->_data = $data;
  218. return true;
  219. } else {
  220. // --- Cache miss ---
  221. if ($this->_sendRequestAndGetResponse()) {
  222. // So the remote server is ok...
  223. $this->save($this->_id, $this->_data, $this->_expires, CACHE_HTTP_REQUEST_GROUP_NAME);
  224. $this->save($this->_id2, $this->_data, 0, CACHE_HTTP_REQUEST_GROUP_NAME);
  225. return true;
  226. } else {
  227. if ($data_sav = $this->get($this->_id2, CACHE_HTTP_REQUEST_GROUP_NAME)) {
  228. // Ok, the "recover cache" is available...
  229. switch ($this->_mode) {
  230. case CACHE_HTTP_REQUEST_KEEP_LOCAL_COPY:
  231. // We make a new local copy and keep it until it expires...
  232. $this->save($this->_id, $data_sav, $this->_expires, CACHE_HTTP_REQUEST_GROUP_NAME);
  233. $this->_data = $data_sav;
  234. return true;
  235. break;
  236. case CACHE_HTTP_REQUEST_RETURN_FALSE:
  237. // We return false
  238. return false;
  239. break;
  240. case CACHE_HTTP_REQUEST_RETURN_PEAR_ERROR:
  241. // We return a PEAR_Error!
  242. return new Cache_Error('Remote file is not available!');
  243. break;
  244. }
  245. } else {
  246. // It's terrible! The remote server is down and definitively no cache available!
  247. return new Cache_Error('Remote server down and no cache available!');
  248. }
  249. }
  250. }
  251. }
  252. // --- Private Methods ---
  253. /**
  254. * Send HTTP request and get the response
  255. *
  256. * @return boolean success or not ?
  257. * @see HTTP_Request
  258. * @access private
  259. */
  260. function _sendRequestAndGetResponse()
  261. {
  262. $this->_request->sendRequest();
  263. $body = $this->_request->getResponseBody();
  264. $code = $this->_request->getResponseCode();
  265. $header = $this->_request->getResponseHeader();
  266. $this->_data = array(
  267. 'body' => $body,
  268. 'code' => $code,
  269. 'header' => $header
  270. );
  271. return (($code==CACHE_HTTP_REQUEST_SUCCESS_RESPONSE_CODE) ? true : false);
  272. }
  273. }
  274. ?>