76
HTTP & Middleware Rob Allen November 2018

HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

  • Upload
    others

  • View
    5

  • Download
    0

Embed Size (px)

Citation preview

Page 1: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

HTTP & MiddlewareRob Allen

   

November 2018

Page 2: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Slim: The C in MVC

Rob Allen ~ @akrabat

Microframework?
Clear and concise codebase
Maps routes to actions
The C in MVC
You pick everything else!
Works best now that we have Composer
Page 3: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

SlimCreated by Josh Lockhart (phptherightway.com)• PSR-2 coding style• PSR-4 autoloading• PSR-7 Request and Response objects• PSR-11 container support• Middleware architecture (PSR-15 upcoming)

Rob Allen ~ @akrabat

Page 4: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

HTTP messages

Rob Allen ~ @akrabat

Page 5: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

HTTP messages

Rob Allen ~ @akrabat

Page 6: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

RequestGET / HTTP/1.1Host: akrabat.comUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:63.0) Gecko/20100101 Firefox/63.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-GB,en;q=0.5Accept-Encoding: gzip, deflate, brConnection: keep-aliveIf-Modified-Since: Mon, 04 Nov 2018 16:21:02 GMTCache-Control: max-age=0

Rob Allen ~ @akrabat

Page 7: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

ResponseHTTP/1.1 200 OKServer: nginx/1.7.6Date: Mon, 04 Nov 2018 16:27:06 GMTContent-Type: text/html; charset=UTF-8Content-Length: 16091Connection: keep-aliveKeep-Alive: timeout=65Vary: Accept-Encoding, CookieCache-Control: max-age=3, must-revalidateContent-Encoding: gzipLast-Modified: Mon, 04 Apr 2016 16:21:02 GMTStrict-Transport-Security: max-age=15768000

<!DOCTYPE html><head>

Rob Allen ~ @akrabat

Page 8: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

How do we do this in PHP?Request:• $_SERVER, $_GET, $_POST, $_COOKIE, $_FILES• apache_request_headers() / getallheaders()• php://input

Rob Allen ~ @akrabat

Page 9: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

How do we do this in PHP?Response:• header()• http_response_code()• header_list() / headers_sent()• echo (& ob_*() family)

Rob Allen ~ @akrabat

Special cases for header():
1. start with 'http/' to set status code
2. 'location' will auto-set the code to 302 for you
Page 10: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

How do we do this in PHP?URI:scheme://username:password@hostname:port/path?arg=value#anchor

• parse_url()• parse_str()• http_build_query()

Rob Allen ~ @akrabat

There's always string concatenation too!
Page 11: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR 7: HTTP messaging• Provides for a uniform access to HTTP messages• A set of interfaces for requests and responses• Created by Framework Interoperability Group

Rob Allen ~ @akrabat

Page 12: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

It's just a set of interfaces

Rob Allen ~ @akrabat

Models RFC 7230 & RFC 7231
UriInteface models RFC 3986
Page 13: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

RequestInterface• Protocol version• HTTP method• URI• Headers• Body

Rob Allen ~ @akrabat

Page 14: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

ServerRequestInterfaceIn addition to RequestInterface:• Server parameters• Query string arguments• Deserialised body• Uploaded Files• Attributes

Rob Allen ~ @akrabat

Page 15: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Response• Protocol version• Status code (& reason phrase)• Headers• Body

Rob Allen ~ @akrabat

Page 16: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Two key things aboutPSR-7

Rob Allen ~ @akrabat

Page 17: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Firstly: Messages and URIsare IMMUTABLE!

Rob Allen ~ @akrabat

Page 18: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

ImmutabilityRequest, ServerRequest, Response & Uri are immutable$uri = new Uri('https://api.joind.in/v2.1/events');$uri2 = $uri->withQuery('?filter=upcoming');$uri3 = $uri->withQuery('?filter=cfp');

Rob Allen ~ @akrabat

Page 19: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

ImmutabilityRequest, ServerRequest, Response & Uri are immutable$uri = new Uri('https://api.joind.in/v2.1/events');$uri2 = $uri->withQuery('?filter=upcoming');$uri3 = $uri->withQuery('?filter=cfp');

public function withQuery($query){ $clone = clone $this; $clone->query = $this->filterQuery($query); return $clone;}

Rob Allen ~ @akrabat

Page 20: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Common mistake$response = new Response();$response->withStatus(302);$response->withHeader('Location', 'http://example.com');

return $response;

Rob Allen ~ @akrabat

Page 21: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

What you meant!$response = new Response();$response = $response->withStatus(302);$response = $response->withHeader('Location', 'http://example.com');

// or

$response = new Response();$response = $response->withStatus(302) ->withHeader('Location', 'http://example.com');

Rob Allen ~ @akrabat

Page 22: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

HeadersReading from the message:$request->hasHeader('Accept'); // boolean$request->getHeader('Accept'); // array$request->getHeaderLine('Accept'); // string

Updating the message:$response = $response->withHeader('Accept', 'application/xml');$response = $response->withAddedHeader('Accept', 'text/xml');$response = $response->withoutHeader('Location');

Rob Allen ~ @akrabat

Page 23: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Secondly: Message bodiesare STREAMS

Rob Allen ~ @akrabat

Page 24: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

StreamsAllows for very large message bodies in a memory efficientmanner$largeFile = __DIR__ . '/brand_guidelines.ppt';

return (new Response()) ->withHeader('Content-Type', 'application/vnd.ms-powerpoint') ->withHeader('Content-Length', (string) filesize($largeFile)) ->withBody(new Stream($largeFile));

Rob Allen ~ @akrabat

Page 25: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Handling stringsFor strings, use the php:://temp stream: $response = $response->withBody(new Stream('php://temp')); $response->getBody()->write('Hello world!');

Rob Allen ~ @akrabat

Page 26: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Mutable!$body->write('Hello');$body->write(' World!');

$response = (new Response()) ->withStatus(200, 'OK') ->withHeader('Content-Type', 'application/html') ->withBody($body);

 Mitigate:

Use read-only streams for server requests and client responses

Rob Allen ~ @akrabat

Page 27: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

ServerRequest AttributesAllow passing of data from one component to the next// component 1function findCountry($request) { $country = $this->geoLocate($request); $request = $request->withAttribute('country', $country); return $request;}

// In an action methodfunction listAction($request, $response, $args) { $country = $request->getAttribute('country'); // do something now that we know the country}

Rob Allen ~ @akrabat

Page 28: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

MiddlewareTurns a request in to a response

Rob Allen ~ @akrabat

Page 29: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Middleware

Rob Allen ~ @akrabat

Page 30: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

This is not new• NodeJS: Connect• Python: WSGI• Ruby: Rack• PHP: StackPHP, Slim

Rob Allen ~ @akrabat

Prior to PSR-7, the PHP ones were not compatible with each other!
Page 31: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-7 Signature (by convention) function ( ServerRequestInterface $request, ResponseInterface $response, callable $next ) : ResponseInterface;

Rob Allen ~ @akrabat

Page 32: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-7 Signature (by convention) function ( ServerRequestInterface $request, ResponseInterface $response, callable $next ) : ResponseInterface;

Rob Allen ~ @akrabat

Page 33: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-7 Signature (by convention) function ( ServerRequestInterface $request, ResponseInterface $response, callable $next ) : ResponseInterface;

Rob Allen ~ @akrabat

Page 34: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-7 Signature (by convention) function ( ServerRequestInterface $request, ResponseInterface $response, callable $next ) : ResponseInterface;

Rob Allen ~ @akrabat

Page 35: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-7 Signature (by convention) function ( ServerRequestInterface $request, ResponseInterface $response, callable $next ) : ResponseInterface;

Rob Allen ~ @akrabat

Page 36: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-7 Middlewarefunction (ServerRequestInterface $request, ResponseInterface $response, callable $next) : ResponseInterface{ // do something before

// call down the chain to the next middleware if ($next) { $response = $next($request, $response); }

// do something with $response after

return $response;}

Rob Allen ~ @akrabat

Page 37: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-7 Middlewarefunction (ServerRequestInterface $request, ResponseInterface $response, callable $next) : ResponseInterface{ // do something before

// call down the chain to the next middleware if ($next) { $response = $next($request, $response); }

// do something with $response after

return $response;}

Rob Allen ~ @akrabat

Page 38: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-7 Middlewarefunction (ServerRequestInterface $request, ResponseInterface $response, callable $next) : ResponseInterface{ // do something before

// call down the chain to the next middleware if ($next) { $response = $next($request, $response); }

// do something with $response after

return $response;}

Rob Allen ~ @akrabat

Page 39: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-7 Middlewarefunction (ServerRequestInterface $request, ResponseInterface $response, callable $next) : ResponseInterface{ // do something before

// call down the chain to the next middleware if ($next) { $response = $next($request, $response); }

// do something with $response after

return $response;}

Rob Allen ~ @akrabat

Page 40: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-7 Middlewarefunction (ServerRequestInterface $request, ResponseInterface $response, callable $next) : ResponseInterface{ // do something before

// call down the chain to the next middleware if ($next) { $response = $next($request, $response); }

// do something with $response after

return $response;}

Rob Allen ~ @akrabat

Page 41: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

What can you do with Middleware?Session CORS CSRFLogging Firewall Debug barAuthentication Throttling Error handlingHTTP cache Honeypot ValidationCSP etc...

Rob Allen ~ @akrabat

Page 42: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Middleware dispatching$app = new Slim\App();

$app->add($mw1);$app->add(SomeMiddleware::class);$app->add('MoreMiddleware');$app->add([$instance, 'methodName']);$app->add(function ($request, $response, $next) { return $next($request, $response);});

$response = $app->run();

Rob Allen ~ @akrabat

Page 43: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Data transfer between middlewareAttributes allow passing of data from one middleware to the nextclass IpAddress{ public function __invoke($request, $response, $next) { $ipAddress = $this->determineClientIpAddress($request); $request = $request->withAttribute('ip_address', $ipAddress); return $response = $next($request, $response); }

// full source: github.com/akrabat/ip-address-middleware}

Rob Allen ~ @akrabat

see: https://github.com/akrabat/ip-address-middleware
Page 44: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Data transfer between middlewareAttributes allow passing of data from one middleware to the nextclass IpAddressMiddleware{ public function __invoke($request, $response, $next) { $ipAddress = $this->determineClientIpAddress($request); $request = $request->withAttribute('ip_address', $ipAddress); return $response = $next($request, $response); }

// full source: github.com/akrabat/ip-address-middleware}

Rob Allen ~ @akrabat

Page 45: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Data transfer between middlewareAttributes allow passing of data from one middleware to the nextclass IpAddressMiddleware{ public function __invoke($request, $response, $next) { $ipAddress = $this->determineClientIpAddress($request); $request = $request->withAttribute('ip_address', $ipAddress); return $response = $next($request, $response); }

// full source: github.com/akrabat/ip-address-middleware}

Rob Allen ~ @akrabat

Page 46: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Data transfer between middlewareAttributes allow passing of data from one middleware to the nextclass IpAddressMiddleware{ public function __invoke($request, $response, $next) { $ipAddress = $this->determineClientIpAddress($request); $request = $request->withAttribute('ip_address', $ipAddress); return $response = $next($request, $response); }

// full source: github.com/akrabat/ip-address-middleware}

Rob Allen ~ @akrabat

Page 47: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Data transfer between middlewareAttributes allow passing of data from one middleware to the nextclass IpAddressMiddleware{ public function __invoke($request, $response, $next) { $ipAddress = $this->determineClientIpAddress($request); $request = $request->withAttribute('ip_address', $ipAddress); return $response = $next($request, $response); }

// full source: github.com/akrabat/ip-address-middleware}

Rob Allen ~ @akrabat

Page 48: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Data transfer between middlewareRead the attributeclass GuardMiddleware{ protected $allowedIps = [10.0.0.1, 192.168.0.1]

public function __invoke($request, $response, $next) { $ipAddress = $request->getAttribute('ip_address'); if (!in_array($ipAddress, $this->allowedIps)) { return $response->withStatus(401); } return $next($request, $response); }}

Rob Allen ~ @akrabat

Page 49: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Data transfer between middlewareRead the attributeclass GuardMiddleware{ protected $allowedIps = [10.0.0.1, 192.168.0.1]

public function __invoke($request, $response, $next) { $ipAddress = $request->getAttribute('ip_address'); if (!in_array($ipAddress, $this->allowedIps)) { return $response->withStatus(401); } return $next($request, $response); }}

Rob Allen ~ @akrabat

Page 50: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Data transfer between middlewareRead the attributeclass GuardMiddleware{ protected $allowedIps = [10.0.0.1, 192.168.0.1]

public function __invoke($request, $response, $next) { $ipAddress = $request->getAttribute('ip_address'); if (!in_array($ipAddress, $this->allowedIps)) { return $response->withStatus(401); } return $next($request, $response); }}

Rob Allen ~ @akrabat

Page 51: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Data transfer between middlewareRead the attributeclass GuardMiddleware{ protected $allowedIps = [10.0.0.1, 192.168.0.1]

public function __invoke($request, $response, $next) { $ipAddress = $request->getAttribute('ip_address'); if (!in_array($ipAddress, $this->allowedIps)) { return $response->withStatus(401); } return $next($request, $response); }}

Rob Allen ~ @akrabat

Page 52: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Data transfer between middlewareRead the attributeclass GuardMiddleware{ protected $allowedIps = [10.0.0.1, 192.168.0.1]

public function __invoke($request, $response, $next) { $ipAddress = $request->getAttribute('ip_address'); if (!in_array($ipAddress, $this->allowedIps)) { return $response->withStatus(401); } return $next($request, $response); }}

Rob Allen ~ @akrabat

Page 53: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-15Two Interfaces from the Framework Interoperability Group:

• Psr\Http\Server\MiddlewareInterface• Psr\Http\Server\RequestHandlerInterface

Rob Allen ~ @akrabat

Page 54: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-15 MiddlewareInterfacenamespace Psr\Http\Server;

use Psr\Http\Message\ResponseInterface;use Psr\Http\Message\ServerRequestInterface;

interface MiddlewareInterface{ public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ) : ResponseInterface;}

Rob Allen ~ @akrabat

Page 55: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-15 MiddlewareInterfacenamespace Psr\Http\Server;

use Psr\Http\Message\ResponseInterface;use Psr\Http\Message\ServerRequestInterface;

interface MiddlewareInterface{ public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ) : ResponseInterface;}

Rob Allen ~ @akrabat

Page 56: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-15 MiddlewareInterfacenamespace Psr\Http\Server;

use Psr\Http\Message\ResponseInterface;use Psr\Http\Message\ServerRequestInterface;

interface MiddlewareInterface{ public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ) : ResponseInterface;}

Rob Allen ~ @akrabat

Page 57: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-15 MiddlewareInterfacenamespace Psr\Http\Server;

use Psr\Http\Message\ResponseInterface;use Psr\Http\Message\ServerRequestInterface;

interface MiddlewareInterface{ public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ) : ResponseInterface;}

Rob Allen ~ @akrabat

Page 58: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-15 MiddlewareInterfacenamespace Psr\Http\Server;

use Psr\Http\Message\ResponseInterface;use Psr\Http\Message\ServerRequestInterface;

interface MiddlewareInterface{ public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ) : ResponseInterface;}

Rob Allen ~ @akrabat

Page 59: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Structure of PSR-15 middlewareclass TimerMiddleware implements MiddlewareInterface{ public function process($request, $handler) { $start = microtime(true);

$response = $handler->handle($request);

$taken = microtime(true) - $start; $response->getBody()->write("<!-- Time: $taken -->");

return $response; }}

Rob Allen ~ @akrabat

Page 60: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Structure of PSR-15 middlewareclass TimerMiddleware implements MiddlewareInterface{ public function process($request, $handler) { $start = microtime(true);

$response = $handler->handle($request);

$taken = microtime(true) - $start; $response->getBody()->write("<!-- Time: $taken -->");

return $response; }}

Rob Allen ~ @akrabat

Page 61: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Structure of PSR-15 middlewareclass TimerMiddleware implements MiddlewareInterface{ public function process($request, $handler) { $start = microtime(true);

$response = $handler->handle($request);

$taken = microtime(true) - $start; $response->getBody()->write("<!-- Time: $taken -->");

return $response; }}

Rob Allen ~ @akrabat

Page 62: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Structure of PSR-15 middlewareclass TimerMiddleware implements MiddlewareInterface{ public function process($request, $handler) { $start = microtime(true);

$response = $handler->handle($request);

$taken = microtime(true) - $start; $response->getBody()->write("<!-- Time: $taken -->");

return $response; }}

Rob Allen ~ @akrabat

Page 63: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Structure of PSR-15 middlewareclass TimerMiddleware implements MiddlewareInterface{ public function process($request, $handler) { $start = microtime(true);

$response = $handler->handle($request);

$taken = microtime(true) - $start; $response->getBody()->write("<!-- Time: $taken -->");

return $response; }}

Rob Allen ~ @akrabat

Page 64: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Structure of PSR-15 middlewareclass TimerMiddleware implements MiddlewareInterface{ public function process($request, $handler) { $start = microtime(true);

$response = $handler->handle($request);

$taken = microtime(true) - $start; $response->getBody()->write("<!-- Time: $taken -->");

return $response; }}

Rob Allen ~ @akrabat

Page 65: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-15 RequestHandlernamespace Psr\Http\Server;

use Psr\Http\Message\ResponseInterface;use Psr\Http\Message\ServerRequestInterface;

interface RequestHandlerInterface{ public function handle( ServerRequestInterface $request ): ResponseInterface;}

Rob Allen ~ @akrabat

The of the the line!
Page 66: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-15 RequestHandlernamespace Psr\Http\Server;

use Psr\Http\Message\ResponseInterface;use Psr\Http\Message\ServerRequestInterface;

interface RequestHandlerInterface{ public function handle( ServerRequestInterface $request ): ResponseInterface;}

Rob Allen ~ @akrabat

Page 67: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

PSR-15 RequestHandlernamespace Psr\Http\Server;

use Psr\Http\Message\ResponseInterface;use Psr\Http\Message\ServerRequestInterface;

interface RequestHandlerInterface{ public function handle( ServerRequestInterface $request ): ResponseInterface;}

Rob Allen ~ @akrabat

Page 68: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

A typical PSR-15 RequestHandlernamespace App\Handler;

// (use statements here)

class HomePageHandler implements RequestHandlerInterface{ public function handle(ServerRequestInterface $request) : ResponseInterface { return new HtmlResponse( '<p>Hello World</p>' ); }}

Rob Allen ~ @akrabat

AKA: Controller action
Page 69: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

A typical PSR-15 RequestHandlernamespace App\Handler;

// (use statements here)

class HomePageHandler implements RequestHandlerInterface{ public function handle(ServerRequestInterface $request) : ResponseInterface { return new HtmlResponse( '<p>Hello World</p>' ); }}

Rob Allen ~ @akrabat

As we implement an interface, you don't get to choose the
name of the action method like you would do in say Laravel
As a result, we name our class well
Page 70: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

A typical PSR-15 RequestHandlernamespace App\Handler;

// (use statements here)

class HomePageHandler implements RequestHandlerInterface{ public function handle(ServerRequestInterface $request) : ResponseInterface { return new HtmlResponse( '<p>Hello World</p>' ); }}

Rob Allen ~ @akrabat

You must create your own response
Page 71: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Frameworks

Rob Allen ~ @akrabat

Page 72: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Zend Expressive: PSR-15$app = new Zend\Expressive\Application(/* ... */);

// add middleware$app->pipe(ErrorHandler::class);$app->pipe(RouteMiddleware::class);$app->pipe(IpAddress::class);$app->pipe(DispatchMiddleware::class);

// add routes$app->get('/', App\Handler\HomePageHandler::class);$app->get('/api/ping', App\Handler\PingHandler::class);

// run$app->run();

Rob Allen ~ @akrabat

Page 73: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Slim Framework: PSR-7$app = new Slim\App();

// add middleware$app->add(IpAddress::class);

// add routes$app->get('/', App\Action\HomePageAction::class);$app->get('/api/ping', 'App\Controller\ApiController:pingAction');

// run$app->run();

Rob Allen ~ @akrabat

Page 74: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Middleware componentsSearch on Packagist• https://packagist.org/search/?q=psr-7%20middleware• https://packagist.org/search/?query=psr-15%20middleware

Ones I use:• akrabat: ip-address-middleware & proxy-detection-middleware• tuupola: cors-middleware, slim-jwt-auth & slim-basic-auth• franzl: whoops-middleware• oscarotero: psr7-middlewares & psr15-middlewares

Rob Allen ~ @akrabat

Page 75: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Resources• https://www.php-fig.org/psr/psr-7• https://www.php-fig.org/psr/psr-15• https://www.php-fig.org/psr/psr-17

• https://mwop.net/blog/2015-01-26-psr-7-by-example.html• https://mwop.net/blog/2018-01-23-psr-15.html

Rob Allen ~ @akrabat

Page 76: HTTP & Middleware - akrabat.com€¦ · Slim. Created by Josh Lockhart (phptherightway.com) • PSR-2 coding style • PSR-4 autoloading • PSR-7 Request and Response objects •

Thank you!Rob Allen

   

http://akrabat.com - @akrabat