Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 0 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ Event-driven, streaming plaintext HTTP and secure HTTPS server for [ReactPHP](ht
* [getHeader()](#getheader)
* [getHeaderLine()](#getheaderline)
* [hasHeader()](#hasheader)
* [expectsContinue()](#expectscontinue)
* [Response](#response)
* [writeContinue()](#writecontinue)
* [writeHead()](#writehead)
* [Install](#install)
* [Tests](#tests)
Expand Down Expand Up @@ -197,18 +195,6 @@ Returns a comma-separated list of all values for this header name or an empty st
The `hasHeader(string $name): bool` method can be used to
check if a header exists by the given case-insensitive name.

#### expectsContinue()

The `expectsContinue(): bool` method can be used to
check if the request headers contain the `Expect: 100-continue` header.

This header MAY be included when an HTTP/1.1 client wants to send a bigger
request body.
See [`writeContinue()`](#writecontinue) for more details.

This will always be `false` for HTTP/1.0 requests, regardless of what
any header values say.

### Response

The `Response` class is responsible for streaming the outgoing response body.
Expand All @@ -227,48 +213,6 @@ See [`writeHead()`](#writehead) for more details.

See the above usage example and the class outline for details.

#### writeContinue()

The `writeContinue(): void` method can be used to
send an intermediary `HTTP/1.1 100 continue` response.

This is a feature that is implemented by *many* HTTP/1.1 clients.
When clients want to send a bigger request body, they MAY send only the request
headers with an additional `Expect: 100-continue` header and wait before
sending the actual (large) message body.

The server side MAY use this header to verify if the request message is
acceptable by checking the request headers (such as `Content-Length` or HTTP
authentication) and then ask the client to continue with sending the message body.
Otherwise, the server can send a normal HTTP response message and save the
client from transfering the whole body at all.

This method is mostly useful in combination with the
[`expectsContinue()`](#expectscontinue) method like this:

```php
$http->on('request', function (Request $request, Response $response) {
if ($request->expectsContinue()) {
$response->writeContinue();
}

$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->end("Hello World!\n");
});
```

Note that calling this method is strictly optional for HTTP/1.1 responses.
If you do not use it, then a HTTP/1.1 client MUST continue sending the
request body after waiting some time.

This method MUST NOT be invoked after calling [`writeHead()`](#writehead).
This method MUST NOT be invoked if this is not a HTTP/1.1 response
(please check [`expectsContinue()`](#expectscontinue) as above).
Calling this method after sending the headers or if this is not a HTTP/1.1
response is an error that will result in an `Exception`
(unless the response has ended/closed already).
Calling this method after the response has ended/closed is a NOOP.

#### writeHead()

The `writeHead(int $status = 200, array $headers = array(): void` method can be used to
Expand Down
18 changes: 0 additions & 18 deletions src/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,24 +149,6 @@ public function hasHeader($name)
return $this->request->hasHeader($name);
}

/**
* Checks if the request headers contain the `Expect: 100-continue` header.
*
* This header MAY be included when an HTTP/1.1 client wants to send a bigger
* request body.
* See [`writeContinue()`] for more details.
*
* This will always be `false` for HTTP/1.0 requests, regardless of what
* any header values say.
*
* @return bool
* @see Response::writeContinue()
*/
public function expectsContinue()
{
return $this->getProtocolVersion() !== '1.0' && '100-continue' === strtolower($this->getHeaderLine('Expect'));
}

public function isReadable()
{
return $this->readable;
Expand Down
59 changes: 0 additions & 59 deletions src/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,65 +66,6 @@ public function isWritable()
return $this->writable;
}

/**
* Sends an intermediary `HTTP/1.1 100 continue` response.
*
* This is a feature that is implemented by *many* HTTP/1.1 clients.
* When clients want to send a bigger request body, they MAY send only the request
* headers with an additional `Expect: 100-continue` header and wait before
* sending the actual (large) message body.
*
* The server side MAY use this header to verify if the request message is
* acceptable by checking the request headers (such as `Content-Length` or HTTP
* authentication) and then ask the client to continue with sending the message body.
* Otherwise, the server can send a normal HTTP response message and save the
* client from transfering the whole body at all.
*
* This method is mostly useful in combination with the
* [`expectsContinue()`] method like this:
*
* ```php
* $http->on('request', function (Request $request, Response $response) {
* if ($request->expectsContinue()) {
* $response->writeContinue();
* }
*
* $response->writeHead(200, array('Content-Type' => 'text/plain'));
* $response->end("Hello World!\n");
* });
* ```
*
* Note that calling this method is strictly optional for HTTP/1.1 responses.
* If you do not use it, then a HTTP/1.1 client MUST continue sending the
* request body after waiting some time.
*
* This method MUST NOT be invoked after calling `writeHead()`.
* This method MUST NOT be invoked if this is not a HTTP/1.1 response
* (please check [`expectsContinue()`] as above).
* Calling this method after sending the headers or if this is not a HTTP/1.1
* response is an error that will result in an `Exception`
* (unless the response has ended/closed already).
* Calling this method after the response has ended/closed is a NOOP.
*
* @return void
* @throws \Exception
* @see Request::expectsContinue()
*/
public function writeContinue()
{
if (!$this->writable) {
return;
}
if ($this->protocolVersion !== '1.1') {
throw new \Exception('Continue requires a HTTP/1.1 message');
}
if ($this->headWritten) {
throw new \Exception('Response head has already been written.');
}

$this->conn->write("HTTP/1.1 100 Continue\r\n\r\n");
}

/**
* Writes the given HTTP message header.
*
Expand Down
36 changes: 0 additions & 36 deletions tests/RequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,6 @@ public function setUp()
$this->stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();
}

/** @test */
public function expectsContinueShouldBeFalseByDefault()
{
$headers = array();
$request = new Request(new Psr('GET', '/', $headers, null, '1.1'), $this->stream);

$this->assertFalse($request->expectsContinue());
}

/** @test */
public function expectsContinueShouldBeTrueIfContinueExpected()
{
$headers = array('Expect' => array('100-continue'));
$request = new Request(new Psr('GET', '/', $headers, null, '1.1'), $this->stream);

$this->assertTrue($request->expectsContinue());
}

/** @test */
public function expectsContinueShouldBeTrueIfContinueExpectedCaseInsensitive()
{
$headers = array('EXPECT' => array('100-CONTINUE'));
$request = new Request(new Psr('GET', '/', $headers, null, '1.1'), $this->stream);

$this->assertTrue($request->expectsContinue());
}

/** @test */
public function expectsContinueShouldBeFalseForHttp10()
{
$headers = array('Expect' => array('100-continue'));
$request = new Request(new Psr('GET', '/', $headers, null, '1.0'), $this->stream);

$this->assertFalse($request->expectsContinue());
}

public function testEmptyHeader()
{
$request = new Request(new Psr('GET', '/', array()), $this->stream);
Expand Down
61 changes: 0 additions & 61 deletions tests/ResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -330,55 +330,6 @@ public function testResponseBodyShouldSkipEmptyChunks()
$response->end();
}

/** @test */
public function writeContinueShouldSendContinueLineBeforeRealHeaders()
{
$conn = $this
->getMockBuilder('React\Socket\ConnectionInterface')
->getMock();
$conn
->expects($this->at(3))
->method('write')
->with("HTTP/1.1 100 Continue\r\n\r\n");
$conn
->expects($this->at(4))
->method('write')
->with($this->stringContains("HTTP/1.1 200 OK\r\n"));

$response = new Response($conn);
$response->writeContinue();
$response->writeHead();
}

/**
* @test
* @expectedException Exception
*/
public function writeContinueShouldThrowForHttp10()
{
$conn = $this
->getMockBuilder('React\Socket\ConnectionInterface')
->getMock();

$response = new Response($conn, '1.0');
$response->writeContinue();
}

/** @expectedException Exception */
public function testWriteContinueAfterWriteHeadShouldThrowException()
{
$conn = $this
->getMockBuilder('React\Socket\ConnectionInterface')
->getMock();
$conn
->expects($this->once())
->method('write');

$response = new Response($conn);
$response->writeHead();
$response->writeContinue();
}

/** @test */
public function shouldRemoveNewlinesFromHeaders()
{
Expand Down Expand Up @@ -551,18 +502,6 @@ public function testWriteHeadAfterCloseIsNoOp()
$response->writeHead();
}

public function testWriteContinueAfterCloseIsNoOp()
{
$input = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock();
$input->expects($this->once())->method('close');
$input->expects($this->never())->method('write');

$response = new Response($input);
$response->close();

$response->writeContinue();
}

public function testEndAfterCloseIsNoOp()
{
$input = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock();
Expand Down