9 The HttpRequest class can be used to execute any HTTP request method.
10 The following example shows a simple GET request where a few query
11 parameters are supplied. Additionally potential cookies will be
12 read from and written to a file.
15 $r = new HttpRequest('http://www.google.com');
17 // store Googles cookies in a dedicated file
19 array( 'cookiestore' => '../cookies/google.txt',
24 array( 'q' => '+"pecl_http" -msg -cvs -list',
29 // HttpRequest::send() returns an HttpMessage object
30 // of type HttpMessage::RESPONSE or throws an exception
32 print $r->send()->getBody();
33 } catch (HttpException $e) {
40 The following example shows an multipart POST request, with two form
41 fields and an image that's supposed to be uploaded to the server.
42 It's a bad habit as well as common practice to issue a redirect after
43 an received POST request, so we'll allow a redirect by enabling the
47 $r = new HttpRequest('http://dev.iworks.at/.print_request.php', HTTP_METH_POST);
49 // if redirects is set to true, a single redirect is allowed;
50 // one can set any reasonable count of allowed redirects
52 array( 'cookies' => array('MyCookie' => 'has a value'),
59 array( 'name' => 'Mike',
60 'mail' => 'mike@php.net',
63 // add the file to post (form name, file name, file type)
64 $r->addPostFile('image', 'profile.jpg', 'image/jpeg');
67 print $r->send()->getBody();
68 } catch (HttpException $e) {
75 It's possible to execute several HttpRequests in parallel with the
76 HttpRequestPool class. HttpRequests to send, do not need to perform
77 the same request method, but can only be attached to one HttpRequestPool
82 $p = new HttpRequestPool;
83 // if you want to set _any_ options of the HttpRequest object,
84 // you need to do so *prior attaching* to the request pool!
85 $p->attach(new HttpRequest('http://pear.php.net', HTTP_METH_HEAD));
86 $p->attach(new HttpRequest('http://pecl.php.net', HTTP_METH_HEAD));
87 } catch (HttpException $e) {
94 // HttpRequestPool implements an iterator over attached HttpRequest objects
96 echo "Checking ", $r->getUrl(), " reported ", $r->getResponseCode(), "\n";
98 } catch (HttpException $e) {
105 You can use a more advanced approach by using the protected interface of
106 the HttpRequestPool class. This allows you to perform some other tasks
107 while the requests are executed.
110 class Pool extends HttpRequestPool
112 public function __construct()
115 new HttpRequest('http://pear.php.net', HTTP_METH_HEAD),
116 new HttpRequest('http://pecl.php.net', HTTP_METH_HEAD)
119 // HttpRequestPool methods socketPerform() and socketSelect() are
120 // protected; one could use this approach to do something else
121 // while the requests are being executed
122 print "Executing requests";
123 for ($i = 0; $this->socketPerform(); $i++) {
124 $i % 10 or print ".";
125 if (!$this->socketSelect()) {
126 throw new HttpException("Socket error!");
134 foreach (new Pool as $r) {
135 echo "Checking ", $r->getUrl(), " reported ", $r->getResponseCode(), "\n";
137 } catch (HttpException $ex) {
144 One of the main key features of HttpResponse is HTTP caching. HttpResponse
145 will calculate an ETag based on the http.etag_mode INI setting as well as
146 it will determine the last modification time of the sent entity. It uses
147 those two indicators to decide if the cache entry on the client side is
148 still valid and will emit an "304 Not Modified" response if applicable.
151 HttpResponse::setCacheControl('public');
152 HttpResponse::setCache(true);
153 HttpResponse::capture();
155 print "This will be cached until content changes!\n";
156 print "Note that this approach will only save the clients download time.\n";
159 - Bandwidth Throttling
161 HttpResponse supports a basic throttling mechanism, which is enabled by
162 setting a throttle delay and a buffer size. PHP will sleep the specified
163 amount of seconds after each sent chunk of specified bytes.
166 // send 5000 bytes every 0.2 seconds, i.e. max ~25kByte/s
167 HttpResponse::setThrottleDelay(0.2);
168 HttpResponse::setBufferSize(5000);
169 HttpResponse::setCache(true);
170 HttpResponse::setContentType('application/x-zip');
171 HttpResponse::setFile('../archive.zip');
172 HttpResponse::send();
186 public function __construct($url, $namespace = '')
188 $this->namespace = $namespace;
189 $this->request = new HttpRequest($url, HTTP_METH_POST);
190 $this->request->setContentType('text/xml');
193 public function setOptions($options = array())
195 return $this->request->setOptions($options);
198 public function addOptions($options)
200 return $this->request->addOptions($options);
203 public function __call($method, $params)
205 if ($this->namespace) {
206 $method = $this->namespace .'.'. $method;
208 $this->request->setPostData(xmlrpc_encode_request($method, $params));
209 $response = $this->request->send();
210 if ($response->getResponseCode() != 200) {
211 throw new Exception($response->getBody(), $response->getResponseCode());
213 return xmlrpc_decode($response->getBody(), 'utf-8');
216 public function getHistory()
218 return $this->request->getHistory();
224 - Simple Feed Aggregator
230 protected $feeds = array();
232 public function __construct($directory = 'feeds')
234 $this->setDirectory($directory);
237 public function setDirectory($directory)
239 $this->directory = $directory;
240 foreach (glob($this->directory .'/*.xml') as $feed) {
241 $this->feeds[basename($feed, '.xml')] = filemtime($feed);
245 public function url2name($url)
247 return preg_replace('/[^\w\.-]+/', '_', $url);
250 public function hasFeed($url)
252 return isset($this->feeds[$this->url2name($url)]);
255 public function addFeed($url)
257 $r = $this->setupRequest($url);
259 $this->handleResponse($r);
262 public function addFeeds($urls)
264 $pool = new HttpRequestPool;
265 foreach ($urls as $url) {
266 $pool->attach($r = $this->setupRequest($url));
270 foreach ($pool as $request) {
271 $this->handleResponse($request);
275 public function getFeed($url)
277 $this->addFeed($url);
278 return $this->loadFeed($this->url2name($url));
281 public function getFeeds($urls)
284 $this->addFeeds($urls);
285 foreach ($urls as $url) {
286 $feeds[] = $this->loadFeed($this->url2name($url));
291 protected function saveFeed($file, $contents)
293 if (file_put_contents($this->directory .'/'. $file .'.xml', $contents)) {
294 $this->feeds[$file] = time();
296 throw new Exception("Could not save feed contents to $file.xml");
300 protected function loadFeed($file)
302 if (isset($this->feeds[$file])) {
303 if ($data = file_get_contents($this->directory .'/'. $file .'.xml')) {
306 throw new Exception("Could not load feed contents from $file.xml");
309 throw new Exception("Unknown feed/file $file.xml");
313 protected function setupRequest($url)
315 $r = new HttpRequest($url);
316 $r->setOptions(array('redirect' => true));
318 $file = $this->url2name($url);
320 if (isset($this->feeds[$file])) {
321 $r->setOptions(array('lastmodified' => $this->feeds[$file]));
327 protected function handleResponse(HttpRequest $r)
329 if ($r->getResponseCode() != 304) {
330 if ($r->getResponseCode() != 200) {
331 throw new Exception("Unexpected response code ". $r->getResponseCode());
333 if (!strlen($body = $r->getResponseBody())) {
334 throw new Exception("Received empty feed from ". $r->getUrl());
336 $this->saveFeed($this->url2name($r->getUrl()), $body);