@@ -13,6 +13,7 @@ Event-driven, streaming plaintext HTTP and secure HTTPS server for [ReactPHP](ht
1313 * [ Request] ( #request )
1414 * [ Response] ( #response )
1515 * [ Middleware] ( #middleware )
16+ * [ LimitConcurrentRequestsMiddleware] ( #limitconcurrentrequestsmiddleware )
1617 * [ RequestBodyBufferMiddleware] ( #requestbodybuffermiddleware )
1718 * [ RequestBodyParserMiddleware] ( #requestbodyparsermiddleware )
1819 * [ Third-Party Middleware] ( #third-party-middleware )
@@ -681,6 +682,59 @@ $server = new StreamingServer(new MiddlewareRunner([
681682]));
682683```
683684
685+ #### LimitConcurrentRequestsMiddleware
686+
687+ The ` LimitConcurrentRequestsMiddleware ` can be used to
688+ limit how many next handlers can be executed concurrently.
689+
690+ If this middleware is invoked, it will check if the number of pending
691+ handlers is below the allowed limit and then simply invoke the next handler
692+ and it will return whatever the next handler returns (or throws).
693+
694+ If the number of pending handlers exceeds the allowed limit, the request will
695+ be queued (and its streaming body will be paused) and it will return a pending
696+ promise.
697+ Once a pending handler returns (or throws), it will pick the oldest request
698+ from this queue and invokes the next handler (and its streaming body will be
699+ resumed).
700+
701+ The following example shows how this middleware can be used to ensure no more
702+ than 10 handlers will be invoked at once:
703+
704+ ``` php
705+ $server = new StreamingServer(new MiddlewareRunner([
706+ new LimitConcurrentRequestsMiddleware(10),
707+ $handler
708+ ]));
709+ ```
710+
711+ Similarly, this middleware is often used in combination with the
712+ [ ` RequestBodyBufferMiddleware ` ] ( #requestbodybuffermiddleware ) (see below)
713+ to limit the total number of requests that can be buffered at once:
714+
715+ ``` php
716+ $server = new StreamingServer(new MiddlewareRunner([
717+ new LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
718+ new RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request
719+ new RequestBodyParserMiddleware(),
720+ $handler
721+ ]));
722+ ```
723+
724+ More sophisticated examples include limiting the total number of requests
725+ that can be buffered at once and then ensure the actual request handler only
726+ processes one request after another without any concurrency:
727+
728+ ``` php
729+ $server = new StreamingServer(new MiddlewareRunner([
730+ new LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
731+ new RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request
732+ new RequestBodyParserMiddleware(),
733+ new LimitConcurrentRequestsMiddleware(1), // only execute 1 handler (no concurrency)
734+ $handler
735+ ]));
736+ ```
737+
684738#### RequestBodyBufferMiddleware
685739
686740One of the built-in middleware is the ` RequestBodyBufferMiddleware ` which
@@ -714,10 +768,18 @@ Similarly, this will immediately invoke the next middleware handler for requests
714768that have an empty request body (such as a simple ` GET ` request) and requests
715769that are already buffered (such as due to another middleware).
716770
771+ Note that the given buffer size limit is applied to each request individually.
772+ This means that if you allow a 2 MiB limit and then receive 1000 concurrent
773+ requests, up to 2000 MiB may be allocated for these buffers alone.
774+ As such, it's highly recommended to use this along with the
775+ [ ` LimitConcurrentRequestsMiddleware ` ] ( #limitconcurrentrequestsmiddleware ) (see above) to limit
776+ the total number of concurrent requests.
777+
717778Usage:
718779
719780``` php
720781$middlewares = new MiddlewareRunner([
782+ new LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
721783 new RequestBodyBufferMiddleware(16 * 1024 * 1024), // 16 MiB
722784 function (ServerRequestInterface $request, callable $next) {
723785 // The body from $request->getBody() is now fully available without the need to stream it
@@ -776,6 +838,7 @@ $handler = function (ServerRequestInterface $request) {
776838};
777839
778840$server = new StreamingServer(new MiddlewareRunner([
841+ new LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
779842 new RequestBodyBufferMiddleware(16 * 1024 * 1024), // 16 MiB
780843 new RequestBodyParserMiddleware(),
781844 $handler
0 commit comments