Skip to content

Commit

Permalink
Implement chunked transfer encoding
Browse files Browse the repository at this point in the history
Fixes #6
  • Loading branch information
thekid committed Jun 25, 2017
1 parent 27a7d22 commit c84b420
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 25 deletions.
24 changes: 22 additions & 2 deletions src/main/php/web/Response.class.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php namespace web;

use lang\IllegalStateException;
use web\io\WriteChunks;

/**
* Response
Expand Down Expand Up @@ -84,11 +85,30 @@ public function close() {
$this->flushed || $this->flush();
}

/**
* Transfers a stream
*
* @param io.streams.InputStream $in
* @param string $mediaType
* @param int $size If omitted, uses chunked transfer encoding
*/
public function transfer($in, $mediaType= 'application/octet-stream', $size= -1) {
$this->headers['Content-Type']= $mediaType;
$this->headers['Content-Length']= $size; // FIXME: Transfer-Encoding chunked!
if (-1 === $size) {
$this->headers['Transfer-Encoding']= 'chunked';
$out= new WriteChunks($this->target);
} else {
$this->headers['Content-Length']= $size;
$out= $this;
}

$this->flush();
$this->target->stream($in);
while ($in->available()) {
$out->write($in->read());
}

$out->close();
$in->close();
}

public function send($content, $mediaType= 'text/html') {
Expand Down
2 changes: 0 additions & 2 deletions src/main/php/web/io/Output.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,4 @@ public function begin($status, $message, $headers);

public function write($bytes);

public function stream($in);

}
25 changes: 25 additions & 0 deletions src/main/php/web/io/WriteChunks.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php namespace web\io;

/**
* Writes Chunked transfer encoding
*
* @see https://tools.ietf.org/html/rfc2616#section-3.6.1
*/
class WriteChunks {
private $target;

/** @param io.streams.OutputStream $target */
public function __construct($target) {
$this->target= $target;
}

/** @param string $chunk */
public function write($chunk) {
$this->target->write(dechex(strlen($chunk))."\r\n".$chunk."\r\n");
}

/** @return void */
public function close() {
$this->target->write("0\r\n\r\n");
}
}
10 changes: 0 additions & 10 deletions src/main/php/xp/web/Output.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,4 @@ public function begin($status, $message, $headers) {
public function write($bytes) {
$this->socket->write($bytes);
}

public function stream($in) {
try {
while ($in->available()) {
$this->socket->write($in->read());
}
} finally {
$in->close();
}
}
}
16 changes: 15 additions & 1 deletion src/test/php/web/unittest/ResponseTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public function send_html() {
}

#[@test]
public function transfer_stream() {
public function transfer_stream_with_length() {
$out= new TestOutput();

$res= new Response($out);
Expand All @@ -121,4 +121,18 @@ public function transfer_stream() {
$out->bytes
);
}

#[@test]
public function transfer_stream_chunked() {
$out= new TestOutput();

$res= new Response($out);
$res->transfer(new MemoryInputStream('<h1>Test</h1>'), 'text/html');

$this->assertEquals(
"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nTransfer-Encoding: chunked\r\n\r\n".
"d\r\n<h1>Test</h1>\r\n0\r\n\r\n",
$out->bytes
);
}
}
10 changes: 0 additions & 10 deletions src/test/php/web/unittest/TestOutput.class.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<?php namespace web\unittest;

use io\streams\Streams;

class TestOutput implements \web\io\Output {
public $bytes;

Expand All @@ -16,12 +14,4 @@ public function begin($status, $message, $headers) {
public function write($bytes) {
$this->bytes.= $bytes;
}

public function stream($in) {
try {
$this->bytes.= Streams::readAll($in);
} finally {
$in->close();
}
}
}

0 comments on commit c84b420

Please sign in to comment.