Speed up web APIs with
Expressive and Swoole

by Enrico Zimuel
Senior Software Engineer
Rogue Wave Software (USA)


phpDay 2018, Verona (Italy), 12th May

About me

Expressive

The PHP framework for middleware applications

  • PSR-7 support (using zend-diactoros)
  • PSR-15 support
  • Piping workflow (using zend-stratigility)
  • Features: routing, dependency injection, templating, error handling
  • Last release 3.0.6, 16th April 2018

A basic web API


use Zend\Diactoros\Response\JsonResponse;
use Zend\Expressive\Application;

$container = require 'config/container.php';

$app = $container->get(Application::class);

$app->pipe('/api/ping', function($request) {
    return new JsonResponse(['ack' => time()]);
});
// or $app->pipe('/api/ping', \App\Handler\PingHandler::class);
$app->run();

Request Handler


use Psr\Http\Message\ResponseInterface; // PSR-7
use Psr\Http\Message\ServerRequestInterface; // PSR-7
use Psr\Http\Server\RequestHandlerInterface; // PSR-15
use Zend\Diactoros\Response\JsonResponse;

class PingHandler implements RequestHandlerInterface
{
    public function handle(
        ServerRequestInterface $request
    ) : ResponseInterface
    {
        return new JsonResponse(['ack' => time()]);
    }
}

Middleware Class


use Psr\Http\Message\ResponseInterface; // PSR-7
use Psr\Http\Message\ServerRequestInterface; // PSR-7
use Psr\Http\Server\MiddlewareInterface; // PSR-15
use Psr\Http\Server\RequestHandlerInterface; // PSR-15

class AuthMiddleware implements MiddlewareInterface
{
    // ...
    public function process(
        ServerRequestInterface $request,
        RequestHandlerInterface $handler
    ) : ResponseInterface
    {
        $user = $this->auth->authenticate($request);
        if (null !== $user) {
            return $handler->handle($request->withAttribute(
                UserInterface::class,
                $user
            ));
        }
        return $this->auth->unauthorizedResponse($request);
    }
}

Example: Routing REST API


$app->route('/api/users[/{id}]', [
    Authentication\AuthenticationMiddleware::class,
    Authorization\AuthorizationMiddleware::class,
    Api\Action\UserAction::class
], ['GET', 'POST', 'PATCH', 'DELETE'], 'api.users');

// or route each HTTP method
$app->get('/api/users[/{id}]', ..., 'api.users.get');
$app->post('/api/users', ..., 'api.users.post');
$app->patch('/api/users/{id}', ..., 'api.users.patch');
$app->delete('/api/users/{id}', ..., 'api.users.delete');

Quick start

You can start using Expressive with composer:

composer create-project zendframework/zend-expressive-skeleton <dir>

Libraries for API

REST example

github.com/ezimuel/zend-expressive-api

Swoole

  • Swoole is an async programming framework for PHP 7
  • PHP extension, install:
    
    pecl install swoole
    
  • Released under Apache license 2.0
  • More info at swoole.co.uk

Features

  • Event-driven, asynchronous programming for PHP
  • Async TCP / UDP / HTTP / Websocket / HTTP2 client/server side API
  • IPv4 / IPv6 / Unixsocket / TCP/ UDP and SSL / TLS support
  • High performance, scalable, support C1000K
  • Fast serializer / unserializer
  • Milliseconds task scheduler

HTTP Server


$http = new swoole_http_server("127.0.0.1", 9501);

$http->on("start", function ($server) {
    echo "Started at http://127.0.0.1:9501\n";
});

$http->on("request", function ($request, $response) {
    $response->header("Content-Type", "text/plain");
    $response->end("Hello World\n");
});

$http->start();

Expressive with Swoole

Use wshafer/swoole-expressive library

Install:


composer require wshafer/swoole-expressive:dev-master

Usage:


vendor/bin/swoole-expressive --host=0.0.0.0 --port=8080

HTTP Server for PSR-7


use Swoole\Http\Request;
use Swoole\Http\Response

$http = new swoole_http_server($host, $port);
$http->on(
    'request',
    function (Request $request, Response $response) use
        ($app, $psr7Request, $swooleResponse) {
        $psrResponse = $app->handle($psr7Request->from($request));
        $swooleResponse->fromPsr7($psrResponse, $response);
    }
);
$http->start();

Swoole vs. nginx vs. Apache

Benchmark results

Expressive with Swoole runs 4x faster than nginx and Apache (source)

Thanks!

Rate this talk at joind.in/talk/bef90

Creative Commons License
This work is licensed under a
Creative Commons Attribution-ShareAlike 3.0 Unported License.
I used reveal.js to make this presentation.