Skip to content

Commit 1802135

Browse files
committed
Update README
1 parent bd908a7 commit 1802135

File tree

2 files changed

+151
-25
lines changed

2 files changed

+151
-25
lines changed

README.md

Lines changed: 120 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ This is an HTTP server which responds with `Hello World` to every request.
2323
$loop = React\EventLoop\Factory::create();
2424
$socket = new React\Socket\Server(8080, $loop);
2525

26-
$http = new Server($socket, function (RequestInterface $request) {
26+
$http = new Server($socket, function (ServerRequestInterface $request) {
2727
return new Response(
2828
200,
2929
array('Content-Type' => 'text/plain'),
@@ -54,7 +54,7 @@ constructor with the respective [request](#request) and
5454
```php
5555
$socket = new React\Socket\Server(8080, $loop);
5656

57-
$http = new Server($socket, function (RequestInterface $request) {
57+
$http = new Server($socket, function (ServerRequestInterface $request) {
5858
return new Response(
5959
200,
6060
array('Content-Type' => 'text/plain'),
@@ -75,7 +75,7 @@ $socket = new React\Socket\SecureServer($socket, $loop, array(
7575
'local_cert' => __DIR__ . '/localhost.pem'
7676
));
7777

78-
$http = new Server($socket, function (RequestInterface $request) {
78+
$http = new Server($socket, function (ServerRequestInterface $request) {
7979
return new Response(
8080
200,
8181
array('Content-Type' => 'text/plain'),
@@ -137,11 +137,13 @@ connections and then processing each incoming HTTP request.
137137
The request object will be processed once the request headers have
138138
been received by the client.
139139
This request object implements the
140+
[PSR-7 ServerRequestInterface](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md#321-psrhttpmessageserverrequestinterface)
141+
which in turn extends the
140142
[PSR-7 RequestInterface](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md#32-psrhttpmessagerequestinterface)
141143
and will be passed to the callback function like this.
142144

143-
```php
144-
$http = new Server($socket, function (RequestInterface $request) {
145+
```php
146+
$http = new Server($socket, function (ServerRequestInterface $request) {
145147
$body = "The method of the request is: " . $request->getMethod();
146148
$body .= "The requested path is: " . $request->getUri()->getPath();
147149

@@ -153,8 +155,41 @@ $http = new Server($socket, function (RequestInterface $request) {
153155
});
154156
```
155157

158+
The `Server` will currently add server-side parameters, analog to the `$_SERVER` variable:
159+
160+
* `server_address`
161+
The current IP address of the server
162+
* `server_port`
163+
The current port of the server
164+
* `remote_address`
165+
The IP address of the request sender
166+
* `remote_port`
167+
Port of the request sender
168+
* `request_time`
169+
Unix timestamp of the moment, the complete request header was received
170+
* `request_time_float`
171+
Unix timestamp in microseconds of the moment, the complete request header was
172+
received
173+
174+
The `server` and `remote` parameters MAY missing if the client or server unexpected
175+
closes the connection.
176+
177+
```php
178+
$http = new Server($socket, function (ServerRequestInterface $request) {
179+
$body = "Your IP is: " . $request->getServerParams()['remote_address'];
180+
181+
return new Response(
182+
200,
183+
array('Content-Type' => 'text/plain'),
184+
$body
185+
);
186+
});
187+
```
188+
156189
For more details about the request object, check out the documentation of
157190
[PSR-7 RequestInterface](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md#32-psrhttpmessagerequestinterface).
191+
and
192+
[PSR-7 ServerRequestInterface](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md#321-psrhttpmessageserverrequestinterface)
158193

159194
Note that the request object will be processed once the request headers have
160195
been received.
@@ -184,7 +219,7 @@ Instead, you should use the `ReactPHP ReadableStreamInterface` which
184219
gives you access to the incoming request body as the individual chunks arrive:
185220

186221
```php
187-
$http = new Server($socket, function (RequestInterface $request) {
222+
$http = new Server($socket, function (ServerRequestInterface $request) {
188223
return new Promise(function ($resolve, $reject) use ($request) {
189224
$contentLength = 0;
190225
$request->getBody()->on('data', function ($data) use (&$contentLength) {
@@ -248,7 +283,7 @@ Note that this value may be `null` if the request body size is unknown in
248283
advance because the request message uses chunked transfer encoding.
249284

250285
```php
251-
$http = new Server($socket, function (RequestInterface $request) {
286+
$http = new Server($socket, function (ServerRequestInterface $request) {
252287
$size = $request->getBody()->getSize();
253288
if ($size === null) {
254289
$body = 'The request does not contain an explicit length.';
@@ -290,6 +325,76 @@ Allowed).
290325
can in fact use a streaming response body for the tunneled application data.
291326
See also [example #21](examples) for more details.
292327

328+
The cookies of the request, will also be added to the request object by the `Server`:
329+
330+
```php
331+
$http = new Server($socket, function (ServerRequestInterface $request) {
332+
$key = 'react';
333+
$value = 'php';
334+
335+
if ($request->getCookieParams() !== array()) {
336+
$body = "Your cookie value is: " . $request->getCookieParams()[$key];
337+
338+
return new Response(
339+
200,
340+
array('Content-Type' => 'text/plain'),
341+
$body
342+
);
343+
}
344+
345+
return new Response(
346+
200,
347+
array(
348+
'Content-Type' => 'text/plain',
349+
'Set-Cookie' => $key . '=' . $value
350+
),
351+
"Your cookie has been set."
352+
);
353+
});
354+
```
355+
356+
The above example should be executed via a web browser, a cookie will be set
357+
on the first request contation the key-value pair 'test=php'.
358+
On a second request to the server the cookie is accessed by the `getCookieParams()`
359+
method, and will be written into the body.
360+
361+
According to the cookie [RFC 6265](https://tools.ietf.org/html/rfc6265#section-4.1.1)
362+
some non-alphanumeric characters are not allowed in the name or value.
363+
Use the `urlencode()` function to encode such
364+
non-alphanumeric characters.
365+
This encoding is also used internally when decoding the name and value of cookies
366+
(which is in line with other implementations, such as PHP's cookie functions).
367+
368+
```php
369+
$http = new Server($socket, function (ServerRequestInterface $request) {
370+
$key = 'react\php';
371+
372+
if (isset($request->getCookieParams()[$key])) {
373+
$body = "Your cookie value is: " . $request->getCookieParams()[$key];
374+
375+
return new Response(
376+
200,
377+
array('Content-Type' => 'text/plain'),
378+
$body
379+
);
380+
}
381+
382+
return new Response(
383+
200,
384+
array(
385+
'Content-Type' => 'text/plain',
386+
'Set-Cookie' => urlencode($key) . '=' . urlencode('test;more')
387+
),
388+
"Your cookie has been set."
389+
);
390+
});
391+
```
392+
393+
The above example will set a cookie in the browser with the key 'react/php' and
394+
the value 'test;more'.
395+
The key and values received by the `getCookieParams()` method
396+
are already decoded.
397+
293398
### Response
294399

295400
The callback function passed to the constructor of the [Server](#server)
@@ -308,7 +413,7 @@ but feel free to use any implemantation of the
308413
`PSR-7 ResponseInterface` you prefer.
309414

310415
```php
311-
$http = new Server($socket, function (RequestInterface $request) {
416+
$http = new Server($socket, function (ServerRequestInterface $request) {
312417
return new Response(
313418
200,
314419
array('Content-Type' => 'text/plain'),
@@ -327,7 +432,7 @@ To prevent this you SHOULD use a
327432
This example shows how such a long-term action could look like:
328433

329434
```php
330-
$server = new \React\Http\Server($socket, function (RequestInterface $request) use ($loop) {
435+
$server = new \React\Http\Server($socket, function (ServerRequestInterface $request) use ($loop) {
331436
return new Promise(function ($resolve, $reject) use ($request, $loop) {
332437
$loop->addTimer(1.5, function() use ($loop, $resolve) {
333438
$response = new Response(
@@ -355,7 +460,7 @@ Note that other implementations of the `PSR-7 ResponseInterface` likely
355460
only support string.
356461

357462
```php
358-
$server = new Server($socket, function (RequestInterface $request) use ($loop) {
463+
$server = new Server($socket, function (ServerRequestInterface $request) use ($loop) {
359464
$stream = new ReadableStream();
360465

361466
$timer = $loop->addPeriodicTimer(0.5, function () use ($stream) {
@@ -389,7 +494,7 @@ If you know the length of your stream body, you MAY specify it like this instead
389494

390495
```php
391496
$stream = new ReadableStream()
392-
$server = new Server($socket, function (RequestInterface $request) use ($loop, $stream) {
497+
$server = new Server($socket, function (ServerRequestInterface $request) use ($loop, $stream) {
393498
return new Response(
394499
200,
395500
array(
@@ -437,7 +542,7 @@ A `Date` header will be automatically added with the system date and time if non
437542
You can add a custom `Date` header yourself like this:
438543

439544
```php
440-
$server = new Server($socket, function (RequestInterface $request) {
545+
$server = new Server($socket, function (ServerRequestInterface $request) {
441546
return new Response(200, array('Date' => date('D, d M Y H:i:s T')));
442547
});
443548
```
@@ -446,7 +551,7 @@ If you don't have a appropriate clock to rely on, you should
446551
unset this header with an empty string:
447552

448553
```php
449-
$server = new Server($socket, function (RequestInterface $request) {
554+
$server = new Server($socket, function (ServerRequestInterface $request) {
450555
return new Response(200, array('Date' => ''));
451556
});
452557
```
@@ -455,7 +560,7 @@ Note that it will automatically assume a `X-Powered-By: react/alpha` header
455560
unless your specify a custom `X-Powered-By` header yourself:
456561

457562
```php
458-
$server = new Server($socket, function (RequestInterface $request) {
563+
$server = new Server($socket, function (ServerRequestInterface $request) {
459564
return new Response(200, array('X-Powered-By' => 'PHP 3'));
460565
});
461566
```
@@ -464,7 +569,7 @@ If you do not want to send this header at all, you can use an empty string as
464569
value like this:
465570

466571
```php
467-
$server = new Server($socket, function (RequestInterface $request) {
572+
$server = new Server($socket, function (ServerRequestInterface $request) {
468573
return new Response(200, array('X-Powered-By' => ''));
469574
});
470575
```

src/Server.php

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
* ```php
2525
* $socket = new React\Socket\Server(8080, $loop);
2626
*
27-
* $http = new Server($socket, function (RequestInterface $request) {
27+
* $http = new Server($socket, function (ServerRequestInterface $request) {
2828
* return new Response(
2929
* 200,
3030
* array('Content-Type' => 'text/plain'),
@@ -45,7 +45,7 @@
4545
* 'local_cert' => __DIR__ . '/localhost.pem'
4646
* ));
4747
*
48-
* $http = new Server($socket, function (RequestInterface $request) {
48+
* $http = new Server($socket, function (ServerRequestInterface $request) {
4949
* return new Response(
5050
* 200,
5151
* array('Content-Type' => 'text/plain'),
@@ -80,6 +80,22 @@
8080
* });
8181
* ```
8282
*
83+
* The server will also emit an `error` event if you return an invalid
84+
* type in the callback function or have a unhandled `Exception`.
85+
* If your callback function throws an exception,
86+
* the `Server` will emit a `RuntimeException` and add the thrown exception
87+
* as previous:
88+
*
89+
* ```php
90+
* $http->on('error', function (Exception $e) {
91+
* echo 'Error: ' . $e->getMessage() . PHP_EOL;
92+
* if ($e->getPrevious() !== null) {
93+
* $previousException = $e->getPrevious();
94+
* echo $previousException->getMessage() . PHP_EOL;
95+
* }
96+
* });
97+
* ```
98+
*
8399
* Note that the request object can also emit an error.
84100
* Check out [request](#request) for more details.
85101
*
@@ -98,15 +114,17 @@ class Server extends EventEmitter
98114
* as HTTP.
99115
*
100116
* For each request, it executes the callback function passed to the
101-
* constructor with the respective [`Request`](#request) and
102-
* [`Response`](#response) objects:
117+
* constructor with the respective [`request`](#request) object:
103118
*
104119
* ```php
105120
* $socket = new React\Socket\Server(8080, $loop);
106121
*
107-
* $http = new Server($socket, function (Request $request, Response $response) {
108-
* $response->writeHead(200, array('Content-Type' => 'text/plain'));
109-
* $response->end("Hello World!\n");
122+
* $http = new Server($socket, function (ServerRequestInterface $request) {
123+
* return new Response(
124+
* 200,
125+
* array('Content-Type' => 'text/plain'),
126+
* "Hello World!\n"
127+
* );
110128
* });
111129
* ```
112130
*
@@ -120,9 +138,12 @@ class Server extends EventEmitter
120138
* 'local_cert' => __DIR__ . '/localhost.pem'
121139
* ));
122140
*
123-
* $http = new Server($socket, function (Request $request, Response $response) {
124-
* $response->writeHead(200, array('Content-Type' => 'text/plain'));
125-
* $response->end("Hello World!\n");
141+
* $http = new Server($socket, function (ServerRequestInterface $request $request) {
142+
* return new Response(
143+
* 200,
144+
* array('Content-Type' => 'text/plain'),
145+
* "Hello World!\n"
146+
* );
126147
* });
127148
*```
128149
*

0 commit comments

Comments
 (0)