Skip to content

Replace request listener with callback function #97

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 16, 2017
Merged
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
46 changes: 21 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,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 React\Http\Server($socket);
$http->on('request', function (Request $request, Response $response) {
$http = new Server($socket, function (Request $request, Response $response) {
$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->end("Hello World!\n");
});
Expand All @@ -47,36 +46,36 @@ See also the [examples](examples).
### Server

The `Server` class is responsible for handling incoming connections and then
emit a `request` event for each incoming HTTP request.
processing each incoming HTTP request.

It attaches itself to an instance of `React\Socket\ServerInterface` which
emits underlying streaming connections in order to then parse incoming data
as HTTP:
as HTTP.

For each request, it executes the callback function passed to the
constructor with the respective [`Request`](#request) and
[`Response`](#response) objects:

```php
$socket = new React\Socket\Server(8080, $loop);

$http = new React\Http\Server($socket);
$http = new Server($socket, function (Request $request, Response $response) {
$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->end("Hello World!\n");
});
```

Similarly, you can also attach this to a
[`React\Socket\SecureServer`](https://github.com/reactphp/socket#secureserver)
in order to start a secure HTTPS server like this:

```php
$socket = new Server(8080, $loop);
$socket = new SecureServer($socket, $loop, array(
$socket = new React\Socket\Server(8080, $loop);
$socket = new React\Socket\SecureServer($socket, $loop, array(
'local_cert' => __DIR__ . '/localhost.pem'
));

$http = new React\Http\Server($socket);
```

For each incoming connection, it emits a `request` event with the respective
[`Request`](#request) and [`Response`](#response) objects:

```php
$http->on('request', function (Request $request, Response $response) {
$http = new Server($socket, function (Request $request, Response $response) {
$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->end("Hello World!\n");
});
Expand All @@ -91,26 +90,23 @@ This ensures you will receive the request body without a delay as expected.
The [Response](#response) still needs to be created as described in the
examples above.

See also [`Request`](#request) and [`Response`](#response) for more details.

> Note that you SHOULD always listen for the `request` event.
Failing to do so will result in the server parsing the incoming request,
but never sending a response back to the client.

Checkout [Request](#request) for details about the request data body.
See also [`Request`](#request) and [`Response`](#response)
for more details(e.g. the request data body).

The `Server` supports both HTTP/1.1 and HTTP/1.0 request messages.
If a client sends an invalid request message, uses an invalid HTTP protocol
version or sends an invalid `Transfer-Encoding` in the request header, it will
emit an `error` event, send an HTTP error response to the client and close the connection:
emit an `error` event, send an HTTP error response to the client and
close the connection:

```php
$http->on('error', function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});
```

The request object can also emit an error. Checkout [Request](#request) for more details.
The request object can also emit an error. Checkout [Request](#request)
for more details.

### Request

Expand All @@ -125,7 +121,7 @@ Listen on the `data` event and the `end` event of the [Request](#request)
to evaluate the data of the request body:

```php
$http->on('request', function (Request $request, Response $response) {
$http = new Server($socket, function (Request $request, Response $response) {
$contentLength = 0;
$request->on('data', function ($data) use (&$contentLength) {
$contentLength += strlen($data);
Expand Down
3 changes: 1 addition & 2 deletions examples/01-hello-world.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
$loop = Factory::create();
$socket = new Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop);

$server = new \React\Http\Server($socket);
$server->on('request', function (Request $request, Response $response) {
$server = new \React\Http\Server($socket, function (Request $request, Response $response) {
$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->end("Hello world!\n");
});
Expand Down
3 changes: 1 addition & 2 deletions examples/02-hello-world-https.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
'local_cert' => isset($argv[2]) ? $argv[2] : __DIR__ . '/localhost.pem'
));

$server = new \React\Http\Server($socket);
$server->on('request', function (Request $reques, Response $response) {
$server = new \React\Http\Server($socket, function (Request $request, Response $response) {
$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->end("Hello world!\n");
});
Expand Down
3 changes: 1 addition & 2 deletions examples/03-handling-body-data.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
$loop = Factory::create();
$socket = new Server(isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop);

$server = new \React\Http\Server($socket);
$server->on('request', function (Request $request, Response $response) {
$server = new \React\Http\Server($socket, function (Request $request, Response $response) {
$contentLength = 0;
$request->on('data', function ($data) use (&$contentLength) {
$contentLength += strlen($data);
Expand Down
77 changes: 56 additions & 21 deletions src/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,36 @@

/**
* The `Server` class is responsible for handling incoming connections and then
* emit a `request` event for each incoming HTTP request.
* processing each incoming HTTP request.
*
* It attaches itself to an instance of `React\Socket\ServerInterface` which
* emits underlying streaming connections in order to then parse incoming data
* as HTTP.
*
* For each request, it executes the callback function passed to the
* constructor with the respective [`Request`](#request) and
* [`Response`](#response) objects:
*
* ```php
* $socket = new React\Socket\Server(8080, $loop);
*
* $http = new React\Http\Server($socket);
* $http = new Server($socket, function (Request $request, Response $response) {
* $response->writeHead(200, array('Content-Type' => 'text/plain'));
* $response->end("Hello World!\n");
* });
* ```
*
* For each incoming connection, it emits a `request` event with the respective
* [`Request`](#request) and [`Response`](#response) objects:
* Similarly, you can also attach this to a
* [`React\Socket\SecureServer`](https://github.com/reactphp/socket#secureserver)
* in order to start a secure HTTPS server like this:
*
* ```php
* $http->on('request', function (Request $request, Response $response) {
* $socket = new React\Socket\Server(8080, $loop);
* $socket = new React\Socket\SecureServer($socket, $loop, array(
* 'local_cert' => __DIR__ . '/localhost.pem'
* ));
*
* $http = new Server($socket, function (Request $request, Response $response) {
* $response->writeHead(200, array('Content-Type' => 'text/plain'));
* $response->end("Hello World!\n");
* });
Expand All @@ -36,22 +53,21 @@
* The [Response](#response) still needs to be created as described in the
* examples above.
*
* See also [`Request`](#request) and [`Response`](#response) for more details.
*
* > Note that you SHOULD always listen for the `request` event.
* Failing to do so will result in the server parsing the incoming request,
* but never sending a response back to the client.
* See also [`Request`](#request) and [`Response`](#response)
* for more details(e.g. the request data body).
*
* The `Server` supports both HTTP/1.1 and HTTP/1.0 request messages.
* If a client sends an invalid request message or uses an invalid HTTP protocol
* version, it will emit an `error` event, send an HTTP error response to the
* client and close the connection:
* If a client sends an invalid request message, uses an invalid HTTP protocol
* version or sends an invalid `Transfer-Encoding` in the request header, it will
* emit an `error` event, send an HTTP error response to the client and
* close the connection:
*
* ```php
* $http->on('error', function (Exception $e) {
* echo 'Error: ' . $e->getMessage() . PHP_EOL;
* });
* ```
*
* The request object can also emit an error. Checkout [Request](#request)
* for more details.
*
Expand All @@ -60,37 +76,55 @@
*/
class Server extends EventEmitter
{
private $callback;

/**
* Creates a HTTP server that accepts connections from the given socket.
*
* It attaches itself to an instance of `React\Socket\ServerInterface` which
* emits underlying streaming connections in order to then parse incoming data
* as HTTP:
* as HTTP.
*
* For each request, it executes the callback function passed to the
* constructor with the respective [`Request`](#request) and
* [`Response`](#response) objects:
*
* ```php
* $socket = new React\Socket\Server(8080, $loop);
*
* $http = new React\Http\Server($socket);
* $http = new Server($socket, function (Request $request, Response $response) {
* $response->writeHead(200, array('Content-Type' => 'text/plain'));
* $response->end("Hello World!\n");
* });
* ```
*
* Similarly, you can also attach this to a
* [`React\Socket\SecureServer`](https://github.com/reactphp/socket#secureserver)
* in order to start a secure HTTPS server like this:
*
* ```php
* $socket = new Server(8080, $loop);
* $socket = new SecureServer($socket, $loop, array(
* $socket = new React\Socket\Server(8080, $loop);
* $socket = new React\Socket\SecureServer($socket, $loop, array(
* 'local_cert' => __DIR__ . '/localhost.pem'
* ));
*
* $http = new React\Http\Server($socket);
* ```
* $http = new Server($socket, function (Request $request, Response $response) {
* $response->writeHead(200, array('Content-Type' => 'text/plain'));
* $response->end("Hello World!\n");
* });
*```
*
* @param \React\Socket\ServerInterface $io
* @param callable $callback
*/
public function __construct(SocketServerInterface $io)
public function __construct(SocketServerInterface $io, $callback)
{
if (!is_callable($callback)) {
throw new \InvalidArgumentException();
}

$io->on('connection', array($this, 'handleConnection'));
$this->callback = $callback;
}

/** @internal */
Expand Down Expand Up @@ -191,7 +225,8 @@ public function handleRequest(ConnectionInterface $conn, RequestInterface $reque
'[]'
);

$this->emit('request', array($request, $response));
$callback = $this->callback;
$callback($request, $response);

if ($contentLength === 0) {
// If Body is empty or Content-Length is 0 and won't emit further data,
Expand Down
Loading