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/search');
17 // store Googles cookies in a dedicated file
20 array( 'cookiestore' => 'google.txt',
25 array( 'q' => '+"pecl_http" -msg -cvs -list',
30 // HttpRequest::send() returns an HttpMessage object
31 // of type HttpMessage::RESPONSE or throws an exception
33 print $r->send()->getBody();
34 } catch (HttpException $e) {
41 The following example shows an multipart POST request, with two form
42 fields and an image that's supposed to be uploaded to the server.
43 It's a bad habit as well as common practice to issue a redirect after
44 an received POST request, so we'll allow a redirect by enabling the
48 $r = new HttpRequest('http://dev.iworks.at/.print_request.php', HTTP_METH_POST);
50 // if redirects is set to true, a single redirect is allowed;
51 // one can set any reasonable count of allowed redirects
53 array( 'cookies' => array('MyCookie' => 'has a value'),
60 array( 'name' => 'Mike',
61 'mail' => 'mike@php.net',
64 // add the file to post (form name, file name, file type)
65 $r->addPostFile('image', 'profile.jpg', 'image/jpeg');
68 print $r->send()->getBody();
69 } catch (HttpException $e) {
76 It's possible to execute several HttpRequests in parallel with the
77 HttpRequestPool class. HttpRequests to send, do not need to perform
78 the same request method, but can only be attached to one HttpRequestPool
83 $p = new HttpRequestPool;
84 // if you want to set _any_ options of the HttpRequest object,
85 // you need to do so *prior attaching* to the request pool!
86 $p->attach(new HttpRequest('http://pear.php.net', HTTP_METH_HEAD));
87 $p->attach(new HttpRequest('http://pecl.php.net', HTTP_METH_HEAD));
88 } catch (HttpException $e) {
95 // HttpRequestPool implements an iterator over attached HttpRequest objects
97 echo "Checking ", $r->getUrl(), " reported ", $r->getResponseCode(), "\n";
99 } catch (HttpException $e) {
106 You can use a more advanced approach by using the protected interface of
107 the HttpRequestPool class. This allows you to perform some other tasks
108 while the requests are executed.
111 class Pool extends HttpRequestPool
113 public function __construct()
116 new HttpRequest('http://pear.php.net', HTTP_METH_HEAD),
117 new HttpRequest('http://pecl.php.net', HTTP_METH_HEAD)
120 // HttpRequestPool methods socketPerform() and socketSelect() are
121 // protected; one could use this approach to do something else
122 // while the requests are being executed
123 print "Executing requests";
124 for ($i = 0; $this->socketPerform(); $i++) {
125 $i % 10 or print ".";
126 if (!$this->socketSelect()) {
127 throw new HttpException("Socket error!");
135 foreach (new Pool as $r) {
136 echo "Checking ", $r->getUrl(), " reported ", $r->getResponseCode(), "\n";
138 } catch (HttpException $ex) {
145 One of the main key features of HttpResponse is HTTP caching. HttpResponse
146 will calculate an ETag based on the http.etag_mode INI setting as well as
147 it will determine the last modification time of the sent entity. It uses
148 those two indicators to decide if the cache entry on the client side is
149 still valid and will emit an "304 Not Modified" response if applicable.
152 HttpResponse::setCacheControl('public');
153 HttpResponse::setCache(true);
154 HttpResponse::capture();
156 print "This will be cached until content changes!\n";
157 print "Note that this approach will only save the clients download time.\n";
160 - Bandwidth Throttling
162 HttpResponse supports a basic throttling mechanism, which is enabled by
163 setting a throttle delay and a buffer size. PHP will sleep the specified
164 amount of seconds after each sent chunk of specified bytes.
167 // send 5000 bytes every 0.2 seconds, i.e. max ~25kByte/s
168 HttpResponse::setThrottleDelay(0.2);
169 HttpResponse::setBufferSize(5000);
170 HttpResponse::setCache(true);
171 HttpResponse::setContentType('application/x-zip');
172 HttpResponse::setFile('../archive.zip');
173 HttpResponse::send();
187 public function __construct($url, $namespace = '')
189 $this->namespace = $namespace;
190 $this->request = new HttpRequest($url, HTTP_METH_POST);
191 $this->request->setContentType('text/xml');
194 public function setOptions($options = array())
196 return $this->request->setOptions($options);
199 public function addOptions($options)
201 return $this->request->addOptions($options);
204 public function __call($method, $params)
206 if ($this->namespace) {
207 $method = $this->namespace .'.'. $method;
209 $this->request->setRawPostData(xmlrpc_encode_request($method, $params));
210 $response = $this->request->send();
211 if ($response->getResponseCode() != 200) {
212 throw new Exception($response->getBody(), $response->getResponseCode());
214 return xmlrpc_decode($response->getBody(), 'utf-8');
217 public function getHistory()
219 return $this->request->getHistory();
225 - Simple Feed Aggregator
231 protected $feeds = array();
233 public function __construct($directory = 'feeds')
235 $this->setDirectory($directory);
238 public function setDirectory($directory)
240 $this->directory = $directory;
241 foreach (glob($this->directory .'/*.xml') as $feed) {
242 $this->feeds[basename($feed, '.xml')] = filemtime($feed);
246 public function url2name($url)
248 return preg_replace('/[^\w\.-]+/', '_', $url);
251 public function hasFeed($url)
253 return isset($this->feeds[$this->url2name($url)]);
256 public function addFeed($url)
258 $r = $this->setupRequest($url);
260 $this->handleResponse($r);
263 public function addFeeds($urls)
265 $pool = new HttpRequestPool;
266 foreach ($urls as $url) {
267 $pool->attach($r = $this->setupRequest($url));
271 foreach ($pool as $request) {
272 $this->handleResponse($request);
276 public function getFeed($url)
278 $this->addFeed($url);
279 return $this->loadFeed($this->url2name($url));
282 public function getFeeds($urls)
285 $this->addFeeds($urls);
286 foreach ($urls as $url) {
287 $feeds[] = $this->loadFeed($this->url2name($url));
292 protected function saveFeed($file, $contents)
294 if (file_put_contents($this->directory .'/'. $file .'.xml', $contents)) {
295 $this->feeds[$file] = time();
297 throw new Exception("Could not save feed contents to $file.xml");
301 protected function loadFeed($file)
303 if (isset($this->feeds[$file])) {
304 if ($data = file_get_contents($this->directory .'/'. $file .'.xml')) {
307 throw new Exception("Could not load feed contents from $file.xml");
310 throw new Exception("Unknown feed/file $file.xml");
314 protected function setupRequest($url)
316 $r = new HttpRequest($url);
317 $r->setOptions(array('redirect' => true));
319 $file = $this->url2name($url);
321 if (isset($this->feeds[$file])) {
322 $r->setOptions(array('lastmodified' => $this->feeds[$file]));
328 protected function handleResponse(HttpRequest $r)
330 if ($r->getResponseCode() != 304) {
331 if ($r->getResponseCode() != 200) {
332 throw new Exception("Unexpected response code ". $r->getResponseCode());
334 if (!strlen($body = $r->getResponseBody())) {
335 throw new Exception("Received empty feed from ". $r->getUrl());
337 $this->saveFeed($this->url2name($r->getUrl()), $body);