DEV Community

Ignacio El Kadre
Ignacio El Kadre

Posted on

1

Swoole and PSR

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:

<?php
use Imefisto\PsrSwoole\ServerRequest as PsrRequest;
use Imefisto\PsrSwoole\ResponseMerger;
use Nyholm\Psr7\Factory\Psr17Factory;
use Slim\Factory\AppFactory;
use Swoole\Http\Request;
use Swoole\Http\Response;
require __DIR__ . '/vendor/autoload.php';
/**
* Create your slim app
*/
$app = AppFactory::create();
/**
* Define your routes
*/
$app->get('/', function ($request, $response, $args) {
$response->getBody()->write("Hello world!");
return $response;
});
$http = new swoole_http_server("0.0.0.0", 9501);
$uriFactory = new Psr17Factory;
$streamFactory = new Psr17Factory;
$responseFactory = new Psr17Factory;
$uploadedFileFactory = new Psr17Factory;
$responseMerger = new ResponseMerger;
$http->on(
'request',
function (
Request $swooleRequest,
Response $swooleResponse
) use (
$uriFactory,
$streamFactory,
$uploadedFileFactory,
$responseFactory,
$responseMerger,
$app
) {
/**
* create psr request from swoole request
*/
$psrRequest = new PsrRequest(
$swooleRequest,
$uriFactory,
$streamFactory,
$uploadedFileFactory
);
/**
* process request (here is where slim handles the request)
*/
$psrResponse = $app->handle($psrRequest);
/**
* merge your psr response with swoole response
*/
$responseMerger->toSwoole(
$psrResponse,
$swooleResponse
)->end();
}
);
$http->start();

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.

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay