Swoole and PSR

Published:

By @imefisto

I've been using Swoole actively for a couple years, maybe more.

It has covered all my needs, the common ones, as those requests similar to "hello world", and the not so common as well, ie.: by combining sync with async processing, couroutines, etc.

For web development, I've being feel comfortable by using a framework to dispatch requests to my model, using middlewares, containers, etc. Particularly I like Slim because of its simplicity.

To use Slim 3 with Swoole, there is a simple and great library: slim-swoole. It allowed me to handle most of the cases. However the library has an invocation to rawContent on Swoole request. That method causes some troubles con big uploads (See related issue).

Others efforts to convert a Swoole Request into a PSR Request has been made. I've looked into them and the general approach is to copy data from Swoole Request into PSR Request and then stop using the Swoole Request. The ones I've analized use the rawContent call on the Swoole Request.

To overcome the issue with the rawContent call on heavy requests, I decided to build my own PSR Request library trying with a lazy approach: This is by initializing the PSR Request with a Swoole Request without copying anything to the PSR Request until the client asks for it, always mantaining the Swoole Request as the source of data.

The idea behind the psr-swoole-native library is to call rawContent only if you need to (this is by calling getBody() on the PSR Request). On an upload operation you can use getUploadedFiles. No need to use getBody. Also you can use getParsedBody if you need other values than the uploaded file.

To keep the library playing with other PSR componentes, I've made mandatory the use of factories in the constructor:

  1. UriFactoryInterface for the getUri method on the PSR Request.
  2. StreamFactoryInterface to create streams (getBody and getUploadedFiles)
  3. UploadedFileFactoryInterface to parse uploadeded files data.

Let's see an example of using the library with Slim 4:

The steps followed in the example are:

  1. Creates an app following the Slim docs, then declares the routes.
  2. Creates the Swoole server and the factories you'll use to create each PSR request.
  3. Inside the "request" event in Swoole server, creates a PSR request and delivery it to the handle method in the Slim app, who should return a PSR response.
  4. Passes the PSR response to the ResponseMerger in order to get the Swoole response populated with data.
  5. Finally calls the end method on the Swoole response.

I won't say anything new, but Swoole is a revolutionary project in PHP world. Also the PSR standards provide an excellent way to get a nice interaction between frameworks and PHP components. I hope the library presented in this article can contribute a little more to this interaction between PHP components and Swoole.