Slide 1

Slide 1 text

Middleware: Between the Framework and the Browser Justin Yost Lead Software Engineer Wirecutter CC BY-NC 4.0 Justin Yost 1

Slide 2

Slide 2 text

Middleware • What is middleware? Software that sits in-between (or in the middle) between our normal PHP application and the browser. CC BY-NC 4.0 Justin Yost 2

Slide 3

Slide 3 text

Middleware • Middleware is designed to act upon Requests and Responses and do something. • The do something is left up to you, modify the Request/ Response, stop it, redirect it, etc. CC BY-NC 4.0 Justin Yost 3

Slide 4

Slide 4 text

Image from Slim Framework Site 4

Slide 5

Slide 5 text

Middleware Use Cases • Caching • Rate Limiting • CORS Headers • Logging • CSRF • IP Blocking • https://github.com/oscarotero/psr7-middlewares • https://github.com/lalop/awesome-psr7 CC BY-NC 4.0 Justin Yost 5

Slide 6

Slide 6 text

Middleware Can and Can Nots • Can • Modify Requests • Modify Responses • Can Not • ! CC BY-NC 4.0 Justin Yost 6

Slide 7

Slide 7 text

Middleware • Build logic external to the application like Rate Limiting into Middleware • Build say a standard set of responses for generic queries into Middleware • Build an entire CRUD application using Middleware, sure. CC BY-NC 4.0 Justin Yost 7

Slide 8

Slide 8 text

Middleware Design • PSR-15: HTTP Server Request Handlers • Uses PSR-7: Requests/Responses CC BY-NC 4.0 Justin Yost 8

Slide 9

Slide 9 text

namespace Psr\Http\Server; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; /** * Participant in processing a server request and response. * * An HTTP middleware component participates in processing an HTTP message: * by acting on the request, generating the response, or forwarding the * request to a subsequent middleware and possibly acting on its response. */ interface MiddlewareInterface { /** * Process an incoming server request. * * Processes an incoming server request in order to produce a response. * If unable to produce the response itself, it may delegate to the provided * request handler to do so. */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface; } CC BY-NC 4.0 Justin Yost 9

Slide 10

Slide 10 text

use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; use Psr\Log\LoggerInterface; class LogMiddleware interface MiddlewareInterface { public function __construct(LoggerInterface $logger) { $this->logger = $logger; } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { // before request $this->logger->info('Request Body {body}', ['body' => $request->getParsedBody()]); // request handled by rest of the stack of middleware and the application $response = $handler->handle($request); // on returning a response return $response; } } CC BY-NC 4.0 Justin Yost 10

Slide 11

Slide 11 text

$dispatcher = new Dispatcher(new ServerFactory(), new Response()); $dispatcher ->addMiddleware(new AuthMiddleware()) ->addMiddleware(new LoggingMiddleware()) ->addMiddleware(new CorsMiddleware()) ->run(); CC BY-NC 4.0 Justin Yost 11

Slide 12

Slide 12 text

class AuthMiddleware interface MiddlewareInterface { public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { // before request if ($this->notAuthed()) { return $this->throwError(); } // request handled by rest of the stack of middleware and the application $response = $handler->handle($request); // on returning a response return $response; } } CC BY-NC 4.0 Justin Yost 12

Slide 13

Slide 13 text

class CorsMiddleware interface MiddlewareInterface { public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { // before request // request handled by rest of the stack of middleware and the application $response = $handler->handle($request); // on returning a response $response = $response->withAddedHeader('Access-Control-Allow-Origin', 'https://myawesome.org'); return $response; } } CC BY-NC 4.0 Justin Yost 13

Slide 14

Slide 14 text

Framework Support • Laravel (not PSR-15) • Symfony (not PSR-15) • CakePHP (PSR-15 full support in Cake 4, currently alpha2) • Slim (PSR-15 full support in Slim4, currently alpha) • Roll your own CC BY-NC 4.0 Justin Yost 14

Slide 15

Slide 15 text

class LaravelBeforeMiddleware { public function handle($request, Closure $next) { // before request // request handled by rest of the stack of middleware and the application return $next($request); } CC BY-NC 4.0 Justin Yost 15

Slide 16

Slide 16 text

class LaravelAfterMiddleware { public function handle($request, Closure $next) { // before request // request handled by rest of the stack of middleware and the application $response = $next($request); // after the response has been crafted return $response } CC BY-NC 4.0 Justin Yost 16

Slide 17

Slide 17 text

class LaravelTerminableMiddleware { public function terminate($request, $response) { // response heading out to the browser and can't be modified } } CC BY-NC 4.0 Justin Yost 17

Slide 18

Slide 18 text

Examples CC BY-NC 4.0 Justin Yost 18

Slide 19

Slide 19 text

Thanks Questions? • twitter.com/justinyost • github.com/justinyost • justinyost.com • linkedin.com/learning/instructors/justin-yost CC BY-NC 4.0 Justin Yost 19