@@ -10,6 +10,8 @@ Event-driven, streaming plaintext HTTP and secure HTTPS server for [ReactPHP](ht
1010* [ Usage] ( #usage )
1111 * [ Server] ( #server )
1212 * [ StreamingServer] ( #streamingserver )
13+ * [ listen()] ( #listen )
14+ * [ error event] ( #error-event )
1315 * [ Request] ( #request )
1416 * [ Request parameters] ( #request-parameters )
1517 * [ Query parameters] ( #query-parameters )
@@ -65,11 +67,10 @@ The `Server` class is responsible for handling incoming connections and then
6567processing each incoming HTTP request.
6668
6769It buffers and parses the complete incoming HTTP request in memory. Once the
68- complete request has been received, it will invoke the request handler.
69-
70- For each request, it executes the callback function passed to the
71- constructor with the respective [ request] ( #request ) object and expects
72- a respective [ response] ( #response ) object in return.
70+ complete request has been received, it will invoke the request handler function.
71+ This request handler function needs to be passed to the constructor and will be
72+ invoked with the respective [ request] ( #request ) object and expects a
73+ [ response] ( #response ) object in return:
7374
7475``` php
7576$server = new Server(function (ServerRequestInterface $request) {
@@ -83,18 +84,79 @@ $server = new Server(function (ServerRequestInterface $request) {
8384});
8485```
8586
86- For most users a server that buffers and parses a requests before handling it over as a
87- PSR-7 request is what they want. The ` Server ` facade takes care of that, and takes the more
88- advanced configuration out of hand. Under the hood it uses [ StreamingServer] ( #streamingserver )
89- with the the three stock middleware using default settings from ` php.ini ` .
87+ Each incoming HTTP request message is always represented by the
88+ [ PSR-7 ` ServerRequestInterface ` ] ( https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface ) ,
89+ see also following [ request] ( #request ) chapter for more details.
90+ Each outgoing HTTP response message is always represented by the
91+ [ PSR-7 ` ResponseInterface ` ] ( https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface ) ,
92+ see also following [ response] ( #response ) chapter for more details.
9093
91- The [ LimitConcurrentRequestsMiddleware ] ( #limitconcurrentrequestsmiddleware ) requires a limit,
92- as such the ` Server ` facade uses the ` memory_limit ` and ` post_max_size ` ini settings to
93- calculate a sensible limit. It assumes a maximum of a quarter of the ` memory_limit ` for
94- buffering and the other three quarter for parsing and handling the requests. The limit is
95- division of half of ` memory_limit ` by ` memory_limit ` rounded up.
94+ In order to process any connections, the server needs to be attached to an
95+ instance of ` React\Socket\ServerInterface ` through the [ ` listen() ` ] ( #listen ) method
96+ as described in the following chapter. In its most simple form, you can attach
97+ this to a [ ` React\Socket\Server ` ] ( https://github.com/reactphp/socket#server )
98+ in order to start a plaintext HTTP server like this:
9699
97- > Note that any errors emitted by the wrapped ` StreamingServer ` are forwarded by ` Server ` .
100+ ``` php
101+ $server = new Server($handler);
102+
103+ $socket = new React\Socket\Server('0.0.0.0:8080', $loop);
104+ $server->listen($socket);
105+ ```
106+
107+ See also the [ ` listen() ` ] ( #listen ) method and the [ first example] ( examples ) for more details.
108+
109+ The ` Server ` class is built as a facade around the underlying
110+ [ ` StreamingServer ` ] ( #streamingserver ) to provide sane defaults for 80% of the
111+ use cases and is the recommended way to use this library unless you're sure
112+ you know what you're doing.
113+
114+ Unlike the underlying [ ` StreamingServer ` ] ( #streamingserver ) , this class
115+ buffers and parses the complete incoming HTTP request in memory. Once the
116+ complete request has been received, it will invoke the request handler
117+ function. This means the [ request] ( #request ) passed to your request handler
118+ function will be fully compatible with PSR-7.
119+
120+ On the other hand, buffering complete HTTP requests in memory until they can
121+ be processed by your request handler function means that this class has to
122+ employ a number of limits to avoid consuming too much memory. In order to
123+ take the more advanced configuration out your hand, it respects setting from
124+ your [ ` php.ini ` ] ( https://www.php.net/manual/en/ini.core.php ) to apply its
125+ default settings. This is a list of PHP settings this class respects with
126+ their respective default values:
127+
128+ ```
129+ memory_limit 128M
130+ post_max_size 8M
131+ enable_post_data_reading 1
132+ max_input_nesting_level 64
133+ max_input_vars 1000
134+
135+ file_uploads 1
136+ upload_max_filesize 2M
137+ max_file_uploads 20
138+ ```
139+
140+ In particular, the ` post_max_size ` setting limits how much memory a single HTTP
141+ request is allowed to consume while buffering its request body. On top of
142+ this, this class will try to avoid consuming more than 1/4 of your
143+ ` memory_limit ` for buffering multiple concurrent HTTP requests. As such, with
144+ the above default settings of ` 128M ` max, it will try to consume no more than
145+ ` 32M ` for buffering multiple concurrent HTTP requests. As a consequence, it
146+ will limit the concurrency to 4 HTTP requests with the above defaults.
147+
148+ It is imperative that you assign reasonable values to your PHP ini settings.
149+ It is usually recommended to either reduce the memory a single request is
150+ allowed to take (set ` post_max_size 1M ` or less) or to increase the total memory
151+ limit to allow for more concurrent requests (set ` memory_limit 512M ` or more).
152+ Failure to do so means that this class may have to disable concurrency and
153+ only handle one request at a time.
154+
155+ Internally, this class automatically assigns these limits to the
156+ [ middleware] ( #middleware ) request handlers as described below. For more
157+ advanced use cases, you may also use the advanced
158+ [ ` StreamingServer ` ] ( #streamingserver ) and assign these middleware request
159+ handlers yourself as described in the following chapters.
98160
99161### StreamingServer
100162
@@ -103,11 +165,11 @@ processing each incoming HTTP request.
103165
104166Unlike the [ ` Server ` ] ( #server ) class, it does not buffer and parse the incoming
105167HTTP request body by default. This means that the request handler will be
106- invoked with a streaming request body.
107-
108- For each request, it executes the callback function passed to the
109- constructor with the respective [ request] ( #request ) object and expects
110- a respective [ response ] ( #response ) object in return.
168+ invoked with a streaming request body. Once the request headers have been
169+ received, it will invoke the request handler function. This request handler
170+ function needs to be passed to the constructor and will be invoked with the
171+ respective [ request] ( #request ) object and expects a [ response ] ( #response )
172+ object in return:
111173
112174``` php
113175$server = new StreamingServer(function (ServerRequestInterface $request) {
@@ -121,51 +183,90 @@ $server = new StreamingServer(function (ServerRequestInterface $request) {
121183});
122184```
123185
186+ Each incoming HTTP request message is always represented by the
187+ [ PSR-7 ` ServerRequestInterface ` ] ( https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface ) ,
188+ see also following [ request] ( #request ) chapter for more details.
189+ Each outgoing HTTP response message is always represented by the
190+ [ PSR-7 ` ResponseInterface ` ] ( https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface ) ,
191+ see also following [ response] ( #response ) chapter for more details.
192+
124193In order to process any connections, the server needs to be attached to an
125- instance of ` React\Socket\ServerInterface ` which emits underlying streaming
126- connections in order to then parse incoming data as HTTP.
194+ instance of ` React\Socket\ServerInterface ` through the [ ` listen() ` ] ( #listen ) method
195+ as described in the following chapter. In its most simple form, you can attach
196+ this to a [ ` React\Socket\Server ` ] ( https://github.com/reactphp/socket#server )
197+ in order to start a plaintext HTTP server like this:
198+
199+ ``` php
200+ $server = new StreamingServer($handler);
201+
202+ $socket = new React\Socket\Server('0.0.0.0:8080', $loop);
203+ $server->listen($socket);
204+ ```
127205
128- You can attach this to a
206+ See also the [ ` listen() ` ] ( #listen ) method and the [ first example] ( examples ) for more details.
207+
208+ The ` StreamingServer ` class is considered advanced usage and unless you know
209+ what you're doing, you're recommended to use the [ ` Server ` ] ( #server ) class
210+ instead. The ` StreamingServer ` class is specifically designed to help with
211+ more advanced use cases where you want to have full control over consuming
212+ the incoming HTTP request body and concurrency settings.
213+
214+ In particular, this class does not buffer and parse the incoming HTTP request
215+ in memory. It will invoke the request handler function once the HTTP request
216+ headers have been received, i.e. before receiving the potentially much larger
217+ HTTP request body. This means the [ request] ( #request ) passed to your request
218+ handler function may not be fully compatible with PSR-7. See also
219+ [ streaming request] ( #streaming-request ) below for more details.
220+
221+ ### listen()
222+
223+ The ` listen(React\Socket\ServerInterface $socket): void ` method can be used to
224+ start processing connections from the given socket server.
225+ The given [ ` React\Socket\ServerInterface ` ] ( https://github.com/reactphp/socket#serverinterface )
226+ is responsible for emitting the underlying streaming connections.
227+ This HTTP server needs to be attached to it in order to process any connections
228+ and pase incoming streaming data as incoming HTTP request messages.
229+ In its most common form, you can attach this to a
129230[ ` React\Socket\Server ` ] ( https://github.com/reactphp/socket#server )
130231in order to start a plaintext HTTP server like this:
131232
132233``` php
234+ $server = new Server($handler);
235+ // or
133236$server = new StreamingServer($handler);
134237
135- $socket = new React\Socket\Server(8080, $loop);
238+ $socket = new React\Socket\Server('0.0.0.0: 8080' , $loop);
136239$server->listen($socket);
137240```
138241
139- See also the ` listen() ` method and the [ first example] ( examples ) for more details.
242+ This example will start listening for HTTP requests on the alternative HTTP port
243+ ` 8080 ` on all interfaces (publicly). As an alternative, it is very common to use
244+ a reverse proxy and let this HTTP server listen on the localhost (loopback)
245+ interface only by using the listen address ` 127.0.0.1:8080 ` instead. This way, you
246+ host your application(s) on the default HTTP port ` 80 ` and only route specific
247+ requests to this HTTP server.
140248
141- Similarly, you can also attach this to a
142- [ ` React\Socket\SecureServer ` ] ( https://github.com/reactphp/socket#secureserver )
143- in order to start a secure HTTPS server like this:
249+ Likewise, it's usually recommended to use a reverse proxy setup to accept
250+ secure HTTPS requests on default HTTPS port ` 443 ` (TLS termination) and only
251+ route plaintext requests to this HTTP server. As an alternative, you can also
252+ accept secure HTTPS requests with this HTTP server by attaching this to a
253+ [ ` React\Socket\Server ` ] ( https://github.com/reactphp/socket#server ) using a
254+ secure TLS listen address, a certificate file and optional ` passphrase ` like this:
144255
145256``` php
257+ $server = new Server($handler);
258+ // or
146259$server = new StreamingServer($handler);
147260
148- $socket = new React\Socket\Server(8080, $loop);
149- $socket = new React\Socket\SecureServer($socket, $loop, array(
261+ $socket = new React\Socket\Server('tls://0.0.0.0:8443', $loop, array(
150262 'local_cert' => __DIR__ . '/localhost.pem'
151263));
152-
153264$server->listen($socket);
154265```
155266
156267See also [ example #11 ] ( examples ) for more details.
157268
158- When HTTP/1.1 clients want to send a bigger request body, they MAY send only
159- the request headers with an additional ` Expect: 100-continue ` header and
160- wait before sending the actual (large) message body.
161- In this case the server will automatically send an intermediary
162- ` HTTP/1.1 100 Continue ` response to the client.
163- This ensures you will receive the request body without a delay as expected.
164- The [ Response] ( #response ) still needs to be created as described in the
165- examples above.
166-
167- See also [ request] ( #request ) and [ response] ( #response )
168- for more details (e.g. the request data body).
269+ ### error event
169270
170271The ` StreamingServer ` supports both HTTP/1.1 and HTTP/1.0 request messages.
171272If a client sends an invalid request message, uses an invalid HTTP protocol
@@ -198,6 +299,8 @@ $server->on('error', function (Exception $e) {
198299Note that the request object can also emit an error.
199300Check out [ request] ( #request ) for more details.
200301
302+ > Note that any errors emitted by the wrapped ` StreamingServer ` are forwarded by ` Server ` .
303+
201304### Request
202305
203306As seen above, the [ ` Server ` ] ( #server ) and [ ` StreamingServer ` ] ( #streamingserver )
@@ -405,6 +508,14 @@ This method operates on the buffered request body, i.e. the request body size
405508is always known, even when the request does not specify a ` Content-Length ` request
406509header or when using ` Transfer-Encoding: chunked ` for HTTP/1.1 requests.
407510
511+ > Note: The ` Server ` automatically takes care of handling requests with the
512+ additional ` Expect: 100-continue ` request header. When HTTP/1.1 clients want to
513+ send a bigger request body, they MAY send only the request headers with an
514+ additional ` Expect: 100-continue ` request header and wait before sending the actual
515+ (large) message body. In this case the server will automatically send an
516+ intermediary ` HTTP/1.1 100 Continue ` response to the client. This ensures you
517+ will receive the request body without a delay as expected.
518+
408519#### Streaming request
409520
410521If you're using the advanced [ ` StreamingServer ` ] ( #streamingserver ) , the
@@ -536,6 +647,14 @@ $server = new StreamingServer(function (ServerRequestInterface $request) {
536647});
537648```
538649
650+ > Note: The ` StreamingServer ` automatically takes care of handling requests with the
651+ additional ` Expect: 100-continue ` request header. When HTTP/1.1 clients want to
652+ send a bigger request body, they MAY send only the request headers with an
653+ additional ` Expect: 100-continue ` request header and wait before sending the actual
654+ (large) message body. In this case the server will automatically send an
655+ intermediary ` HTTP/1.1 100 Continue ` response to the client. This ensures you
656+ will receive the streaming request body without a delay as expected.
657+
539658#### Request method
540659
541660Note that the server supports * any* request method (including custom and non-
0 commit comments