Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
legionth committed Mar 20, 2017
1 parent 7ec68c5 commit b27a34b
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 77 deletions.
130 changes: 55 additions & 75 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,6 @@ Event-driven, streaming plaintext HTTP and secure HTTPS server for [ReactPHP](ht
* [Usage](#usage)
* [Server](#server)
* [Request](#request)
* [getMethod()](#getmethod)
* [getQueryParams()](#getqueryparams)
* [getProtocolVersion()](#getprotocolversion)
* [getHeaders()](#getheaders)
* [getHeader()](#getheader)
* [getHeaderLine()](#getheaderline)
* [hasHeader()](#hasheader)
* [Response](#response)
* [writeHead()](#writehead)
* [Install](#install)
Expand All @@ -31,7 +24,7 @@ This is an HTTP server which responds with `Hello World` to every request.
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server(8080, $loop);

$http = new Server($socket, function (Request $request, Response $response) {
$http = new Server($socket, function (RequestInterface $request, Response $response) {
$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->end("Hello World!\n");
});
Expand Down Expand Up @@ -59,7 +52,7 @@ constructor with the respective [`Request`](#request) and
```php
$socket = new React\Socket\Server(8080, $loop);

$http = new Server($socket, function (Request $request, Response $response) {
$http = new Server($socket, function (RequestInterface $request, Response $response) {
$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->end("Hello World!\n");
});
Expand All @@ -75,7 +68,7 @@ $socket = new React\Socket\SecureServer($socket, $loop, array(
'local_cert' => __DIR__ . '/localhost.pem'
));

$http = new Server($socket, function (Request $request, Response $response) {
$http = new Server($socket, function (RequestInterface $request, Response $response) {
$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->end("Hello World!\n");
});
Expand Down Expand Up @@ -110,93 +103,80 @@ for more details.

### Request

The `Request` class is responsible for streaming the incoming request body
and contains meta data which was parsed from the request headers.
If the request body is chunked-encoded, the data will be decoded and emitted on the data event.
The `Transfer-Encoding` header will be removed.

It implements the `ReadableStreamInterface`.

Listen on the `data` event and the `end` event of the [Request](#request)
to evaluate the data of the request body:
A HTTP request will be sent by a client to the [Server](#server).
The `Server` will receive this request on the `data` event and
is responsible to create a request object from this data.
This object will be passed to the callback function.

The request is an instance of [PSR-7 RequestInterface](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md#32-psrhttpmessagerequestinterface).

As defined in PSR-7, the `getBody()` method returns a stream instance
which implements the [PSR-7 StreamInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagestreaminterface).
Note that the incoming request will be processed once the request headers have
been received, which implies that the (potentially much larger) request body
may still be outstanding (in a streaming state).
However, most of the `PSR-7 StreamInterface` methods have been
designed under the assumption of being in control of the request body.
Given that this does not apply to this server, the following
`PSR-7 StreamInterface` methods are not used and SHOULD NOT be called:
`tell()`, `eof()`, `seek()`, `rewind()`, `write()` and `read()`.
Instead, the returned stream instance *also* implements the
[ReactPHP ReadableStreamInterface](https://github.com/reactphp/stream#readablestreaminterface)
which gives you access to the incoming request body as the individual chunks
arrive:

```php
$http = new Server($socket, function (Request $request, Response $response) {
$http = new Server($socket, function (RequestInterface $request, Response $response) {
$contentLength = 0;
$request->on('data', function ($data) use (&$contentLength) {
$body = $request->getBody();
$body->on('data', function ($data) use (&$contentLength) {
$contentLength += strlen($data);
});

$request->on('end', function () use ($response, &$contentLength){
$body->on('end', function () use ($response, &$contentLength){
$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->end("The length of the submitted request body is: " . $contentLength);
});

// an error occures e.g. on invalid chunked encoded data or an unexpected 'end' event
$request->on('error', function (\Exception $exception) use ($response, &$contentLength) {
$body->on('error', function (\Exception $exception) use ($response, &$contentLength) {
$response->writeHead(400, array('Content-Type' => 'text/plain'));
$response->end("An error occured while reading at length: " . $contentLength);
});
});
```

An error will just `pause` the connection instead of closing it. A response message
can still be sent.

A `close` event will be emitted after an `error` or `end` event.

The constructor is internal, you SHOULD NOT call this yourself.
The `Server` is responsible for emitting `Request` and `Response` objects.

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

#### getMethod()

The `getMethod(): string` method can be used to
return the request method.

#### getPath()

The `getPath(): string` method can be used to
return the request path.

#### getQueryParams()
The above example simply counts the number of bytes received in the request body.
This can be used as a skeleton for buffering or processing the request body.

The `getQueryParams(): array` method can be used to
return an array with all query parameters ($_GET).
If you only want to know the request body size, you can use its `getSize()`
method.
This method returns the complete size of the request body as defined by the
message boundaries.
This value may be `0` if the request message does not contain a request body
(such as a simple `GET` request).
Note that this value may be `null` if the request body size is unknown in
advance because the request message uses chunked transfer encoding.

#### getProtocolVersion()

The `getProtocolVersion(): string` method can be used to
return the HTTP protocol version (such as "1.0" or "1.1").

#### getHeaders()

The `getHeaders(): array` method can be used to
return an array with ALL headers.

The keys represent the header name in the exact case in which they were
originally specified. The values will be an array of strings for each
value for the respective header name.

#### getHeader()

The `getHeader(string $name): string[]` method can be used to
retrieve a message header value by the given case-insensitive name.

Returns a list of all values for this header name or an empty array if header was not found

#### getHeaderLine()

The `getHeaderLine(string $name): string` method can be used to
retrieve a comma-separated string of the values for a single header.
```php
$http = new Server($socket, function (RequestInterface $request, Response $response) {
$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->write("Request method: " . $request->getMethod() . "\n");
if ($request->getBody()->getSize() !== null) {
$response->write("Request body size: " . $request->getBody()->getSize() . "\n");
}
$response->end("The requested path is: " . $request->getUri()->getPath());
});
```

Returns a comma-separated list of all values for this header name or an empty string if header was not found
The server automatically takes care of decoding chunked transfer encoding
and will only emit the actual payload as data.
The `Transfer-Encoding` header will be removed.

#### hasHeader()
An error will just `pause` the connection instead of closing it. A response message
can still be sent.

The `hasHeader(string $name): bool` method can be used to
check if a header exists by the given case-insensitive name.
A `close` event will be emitted after an `error` or `end` event.

### Response

Expand Down
4 changes: 2 additions & 2 deletions src/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* ```php
* $socket = new React\Socket\Server(8080, $loop);
*
* $http = new Server($socket, function (Request $request, Response $response) {
* $http = new Server($socket, function (RequestInterface $request, Response $response) {
* $response->writeHead(200, array('Content-Type' => 'text/plain'));
* $response->end("Hello World!\n");
* });
Expand All @@ -38,7 +38,7 @@
* 'local_cert' => __DIR__ . '/localhost.pem'
* ));
*
* $http = new Server($socket, function (Request $request, Response $response) {
* $http = new Server($socket, function (RequestInterface $request, Response $response) {
* $response->writeHead(200, array('Content-Type' => 'text/plain'));
* $response->end("Hello World!\n");
* });
Expand Down

0 comments on commit b27a34b

Please sign in to comment.