2 // +----------------------------------------------------------------------+
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 // +----------------------------------------------------------------------+
18 // $Id: HTTP_Request.php 174777 2004-12-15 09:09:33Z dufuz $
20 require_once 'Cache.php';
21 require_once 'HTTP/Request.php';
23 define('CACHE_HTTP_REQUEST_GROUP_NAME', 'cache_http_request');
24 define('CACHE_HTTP_REQUEST_SUCCESS_RESPONSE_CODE', 200);
25 define('CACHE_HTTP_REQUEST_KEEP_LOCAL_COPY', 1);
26 define('CACHE_HTTP_REQUEST_RETURN_FALSE', 2);
27 define('CACHE_HTTP_REQUEST_RETURN_PEAR_ERROR', 3);
32 * The classical example is :
34 * You want to get news from another site through RSS remote files. But you
35 * don't want to access to to the remote site at every time you display
36 * its news on your site. Because, if the remote site is down or slow...
37 * So you you need a class which makes a local cache copy of the remote file.
38 * Every x hours, the cache is updated. But if the remote site is down, the
39 * local cache copy is keeped (you can also get error messages if you want).
41 * So you need this class!
43 * Cache_HTTP_Request inherits from Cache and use HTTP_Request to access to
49 * require_once('Cache/HTTP_Request.php');
51 * $cache = &new Cache_HTTP_Request('http://www.php.net', null, 'file', null, 3600);
52 * $cache->sendRequest();
53 * $remoteFileBody = $cache->getResponseBody();
58 * @author Fabien MARTY <fabien.marty@free.fr>
59 * @version $Id: HTTP_Request.php 174777 2004-12-15 09:09:33Z dufuz $
63 class Cache_HTTP_Request extends Cache
66 // --- Private properties ---
69 * Lifetime in seconds (0 endless)
78 * @var object $_request
83 * Cache id for the classic cache file
91 * Cache id for the endless cache file
101 * @see getReponseBody(), getReponseHeader(), getReponseCode()
106 // --- Public methods ---
111 * @param $url The url to access
112 * @param $params Associative array of parameters which can be:
113 * method - Method to use, GET, POST etc
114 * http - HTTP Version to use, 1.0 or 1.1
115 * user - Basic Auth username
116 * pass - Basic Auth password
117 * proxy_host - Proxy server host
118 * proxy_port - Proxy server port
119 * proxy_user - Proxy auth username
120 * proxy_pass - Proxy auth password
121 * @param string $container Name of container class
122 * @param array $containerOptions Array with container class options
123 * @param int $mode What to do when the remote server is down :
124 * CACHE_HTTP_REQUEST_KEEP_LOCAL_COPY or
125 * CACHE_HTTP_REQUEST_RETURN_FALSE or
126 * CACHE_HTTP_REQUEST_RETURN_PEAR_ERROR
127 * @param int $expires lifetime of the cached data in seconds - 0 for endless
128 * @see Cache, HTTP_Request
131 function Cache_HTTP_Request($url, $params = null, $container = 'file',
132 $containerOptions = null, $expires = 3600,
133 $mode = CACHE_HTTP_REQUEST_KEEP_LOCAL_COPY)
135 if (!isset($params)) {
139 if (!isset($containerOptions)) {
140 $containerOptions = array (
141 'cache_dir' => '/tmp/',
142 'filename_prefix' => 'cache_'
145 $this->Cache($container, $containerOptions);
146 $this->_request = &new HTTP_Request($url, $params);
147 $this->_id = md5($url.serialize($params));
148 $this->_id2 = md5($this->_id); // we need two keys
149 $this->_mode = $mode;
150 $this->_expires = $expires;
158 function _Cache_HTTP_Request()
164 * Get and return the response body (null if no data available)
167 * @return mixed response body
170 function getResponseBody()
172 return $this->_data['body'];
176 * Get and return the response code (null if no data available)
179 * @return mixed response code
182 function getResponseCode()
184 return $this->_data['code'];
188 * Get and return the response header (null if no data available)
191 * @return mixed response header
194 function getResponseHeader()
196 return $this->_data['header'];
201 * Set a new mode when the server is down
203 * @param int $newMode What to do when the remote server is down :
204 * CACHE_HTTP_REQUEST_KEEP_LOCAL_COPY or
205 * CACHE_HTTP_REQUEST_RETURN_FALSE or
206 * CACHE_HTTP_REQUEST_RETURN_PEAR_ERROR
209 function setMode($newMode)
211 $this->_mode = $newMode;
215 * Send the HTTP request or use the cache system
217 * If there is a cache file for this HTTP request, the request is not re-sent.
218 * Cached response is used. Yet, if the cache is expired, the HTTP request
219 * is re-sent. Then, if the remote server is down, this method will return :
220 * (depending on the selected mode)
222 * - a PEAR_Error or (better)
223 * - true and the local copy of the latest valid response will be used.
226 * For the last choice, there is a technical tips.
227 * Indeed, there are two cache files. The first one (id key) is a classical one
228 * with the given lifetime. But it can be removed by automatic garbage collection
229 * for example. So to be able to use the latest valid response (when the remote
230 * server is dead), we make a second cache file with no lifetime (id2 key).
232 * @return mixed true or false or a PEAR_ERROR
235 function sendRequest()
237 if ($data = $this->get($this->_id, CACHE_HTTP_REQUEST_GROUP_NAME)) {
239 $this->_data = $data;
242 // --- Cache miss ---
243 if ($this->_sendRequestAndGetResponse()) {
244 // So the remote server is ok...
245 $this->save($this->_id, $this->_data, $this->_expires, CACHE_HTTP_REQUEST_GROUP_NAME);
246 $this->save($this->_id2, $this->_data, 0, CACHE_HTTP_REQUEST_GROUP_NAME);
249 if ($data_sav = $this->get($this->_id2, CACHE_HTTP_REQUEST_GROUP_NAME)) {
250 // Ok, the "recover cache" is available...
251 switch ($this->_mode) {
252 case CACHE_HTTP_REQUEST_KEEP_LOCAL_COPY:
253 // We make a new local copy and keep it until it expires...
254 $this->save($this->_id, $data_sav, $this->_expires, CACHE_HTTP_REQUEST_GROUP_NAME);
255 $this->_data = $data_sav;
258 case CACHE_HTTP_REQUEST_RETURN_FALSE:
262 case CACHE_HTTP_REQUEST_RETURN_PEAR_ERROR:
263 // We return a PEAR_Error!
264 return new Cache_Error('Remote file is not available!');
268 // It's terrible! The remote server is down and definitively no cache available!
269 return new Cache_Error('Remote server down and no cache available!');
275 // --- Private Methods ---
278 * Send HTTP request and get the response
280 * @return boolean success or not ?
284 function _sendRequestAndGetResponse()
286 $this->_request->sendRequest();
287 $body = $this->_request->getResponseBody();
288 $code = $this->_request->getResponseCode();
289 $header = $this->_request->getResponseHeader();
290 $this->_data = array(
295 return (($code==CACHE_HTTP_REQUEST_SUCCESS_RESPONSE_CODE) ? true : false);