2 title: PECL::HTTP - A nasty bug and a new example
8 I just fixed a nasty bug which caused GZIP encoded files (speak tgz etc.) to
9 be decoded. While it'll just eat **some** memory on a 200 response (besides
10 that the body is not what one would expect), it'll eat all memory on 206
11 (partial content) responses because the part is fed through zlib. I'll just
12 need to revisit the HTTP RFC to check if checking for the "Vary" response
13 header is the best bet before I drop the new release.
15 Ok, that's it about the bad news -- I also added a new example to the tutorial
16 which shows how one could efficiently download big files. Using the example
20 $bigget = BigGet::url('http://example.com/big_file.bin');
21 $bigGet->saveTo('big_file.bin');
23 class BigGetRequest extends HttpRequest
28 class BigGet extends HttpRequestPool
35 private $files = array();
37 static function url($url)
39 $head = new HttpRequest($url, HttpRequest::METH_HEAD);
40 $headers = $head->send()->getHeaders();
43 if (!isset($headers['Accept-Ranges'])) {
44 throw new HttpExcpetion("Did not receive an ".
45 "Accept-Ranges header from HEAD $url");
47 if (!isset($headers['Content-Length'])) {
48 throw new HttpException("Did not receive a ".
49 "Content-Length header from HEAD $url");
54 $bigget->size = $headers['Content-Length'];
58 function saveTo($file)
61 if ($w = fopen($file, 'wb')) {
62 echo "nCopying temp files to $file ...n";
63 foreach (glob("bigget_????.tmp") as $tmp) {
65 if ($r = fopen($tmp, 'rb')) {
66 stream_copy_to_stream($r, $w);
78 // use max 3 simultanous requests with a req size of 1MiB
79 while ($this->count < 3 &&
80 -1 != $offset = $this->getRangeOffset()) {
81 $this->attachNew($offset);
84 while ($this->socketPerform()) {
85 if (!$this->socketSelect()) {
86 throw new HttpSocketException;
91 private function attachNew($offset)
93 $stop = min($this->count * self::SIZE + self::SIZE,
96 echo "Attaching new request to get range: $offset-$stopn";
98 $req = new BigGetRequest(
100 HttpRequest::METH_GET,
103 'Range' => "bytes=$offset-$stop"
108 $req->id = $this->count++;
111 private function getRangeOffset()
113 return ($this->size >=
114 $start = $this->count * self::SIZE) ? $start : -1;
117 protected function socketPerform()
120 $rc = parent::socketPerform();
121 } catch (HttpRequestPoolException $x) {
122 foreach ($x->exceptionStack as $e) {
123 echo $e->getMessage(), "n";
127 foreach ($this->getFinishedRequests() as $r) {
130 if (206 != $rc = $r->getResponseCode()) {
131 throw new HttpException(
132 "Unexpected response code: $rc");
136 sprintf("bigget_%04d.tmp", $r->id),
137 $r->getResponseBody());
139 if (-1 != $offset = $this->getRangeOffset()) {
140 $this->attachNew($offset);