Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The HttpKernelInterface is a lie

The HttpKernelInterface is a lie

Igor Wiedler

May 23, 2013
Tweet

More Decks by Igor Wiedler

Other Decks in Programming

Transcript

  1. the HttpKernelInterface is a lie

  2. @igorwesome

  3. None
  4. “Interface” Protocol Communication Message passing

  5. Catherine Please, from The Noun Project

  6. Paulo Sá Ferreira - Purple Matter, from The Noun Project

  7. hi!

  8. None
  9. 10010101110100100

  10. 1001010111010010000110101 Massimiliano Mauro, from The Noun Project

  11. Sergey Shmidt, from The Noun Project aloha!

  12. yay!

  13. 00101000011101100102

  14. None
  15. None
  16. None
  17. None
  18. None
  19. 10010111001010001011

  20. 1234 4321

  21. foo bar baz foo baz Patrick n Hawaii, from The

    Noun Project
  22. foo moo Anuar Zhumaev, from The Noun Project

  23. find src -name '*.php' | grep -iv tests | cut

    -f2- -d/ | cut -f1 -d\. | awk '{ print length, $0 }' | sort -n | tr / \\ ;
  24. Tim Boelaars, from The Noun Project

  25. None
  26. nc

  27. /\_/\ / 0 0 \ ====v==== \ W / |

    | _ / ___ \ / / / \ \ | (((-----)))-' / ( ___ \__.=|___E /
  28. None
  29. data Dmitry Baranovskiy, from The Noun Project

  30. xinetd

  31. None
  32. /etc/xinet.d/<service> service <service> { disable = no socket_type = stream

    protocol = tcp user = <user> wait = no server = /usr/local/bin/<program> }
  33. /etc/xinet.d/fortune service fortune { disable = no socket_type = stream

    protocol = tcp user = xinetd wait = no server = /usr/local/bin/fortune }
  34. #!/bin/bash fortune | cowsay

  35. $ nc <host> 7777

  36. $ nc <host> 7777 ______________________________________ < Eat right, stay fit,

    and die anyway. > -------------------------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
  37. /etc/xinet.d/cowsay service cowsay { disable = no socket_type = stream

    protocol = tcp user = xinetd wait = no server = /usr/games/cowsay }
  38. $ echo 'moo' | nc <host> 7778

  39. $ echo 'moo' | nc <host> 7778 _____ < moo

    > ----- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
  40. #!/usr/bin/php <?php while (!feof(STDIN)) { echo transform(fgets(STDIN)); }

  41. cgi

  42. The Common Gateway Interface (CGI) [22] allows an HTTP [1],

    [4] server and a CGI script to share responsibility for responding to client requests. RFC 3875
  43. xinetd tcp http httpd

  44. http httpd script cgi

  45. script env vars data headers data

  46. GET / HTTP/1.1 Host: igor.io Accept: */* REQUEST_METHOD = GET

    PATH_INFO = / HTTP_HOST = igor.io HTTP_ACCEPT = */* SERVER_NAME = igor.io =>
  47. Content-Type: text/html <!DOCTYPE html> <html> ... </html>

  48. curl => inetd | web | cgi

  49. fcgi

  50. script

  51. sockets are the new pipes

  52. • 1991: HTTP • 1993: CGI • 1995: PHP •

    1996: FastCGI
  53. • 1997: Java Servlet • 2003: Python WSGI • 2007:

    Ruby Rack • 2009: Perl PSGI • 2011: Symfony2 HttpKernelInterface
  54. rack

  55. class HelloWorld def call(env) [ 200, {"Content-Type" => "text/plain"}, ["Hello

    world!"] ] end end
  56. function helloWorld(array $env) { return [ 200, ["Content-Type" => "text/plain"],

    ["Hello world!"], ]; }
  57. sapi

  58. $_SERVER header echo exit

  59. HttpKernelInterface

  60. sapi kernel

  61. tcp websocket HTTP/1.1 <soap> {“JSON”}

  62. “legacy” apps: it’s all great until exit;

  63. myths:

  64. myths: caching

  65. myths: caching (use varnish)

  66. myths: caching (use varnish) functional tests

  67. CgiHttpKernel adapter from kernel to cgi functional test “legacy” apps

  68. kernel CGI

  69. kernel CGI anything!

  70. export SCRIPT_NAME=/app.php export SCRIPT_FILENAME=/var/www/app.php export PATH_INFO=/foo export QUERY_STRING="bar=baz&qux=quux" export REQUEST_URI=/foo

    export REQUEST_METHOD=GET php-cgi app.php
  71. $kernel = new CgiHttpKernel(__DIR__.'/app'); $request = Request::create('/index.php'); $response = $kernel->handle($request);

    var_dump($response->getContent());
  72. use Symfony\Component\HttpKernel\Client; $client = new Client($kernel); $crawler = $client->request('GET', '/index.php');

  73. caution: it’s slow (but could be optimized)

  74. Where is the value?

  75. REQ REP

  76. fcgi roles

  77. authorizer httpd responder filter

  78. rack middlewares

  79. class EmptyDecorator def initialize(app) @app = app end def call(env)

    @app.call(env) end end
  80. class CommonLogger def initialize(app, logger=nil) @app = app @logger =

    logger end def call(env) began_at = Time.now response = @app.call(env) status, header, _ = response log(env, status, header, began_at) response end private def log(env, status, header, began_at) ... end end
  81. class CommonLogger def initialize(app, logger=nil) @app = app @logger =

    logger end def call(env) began_at = Time.now response = @app.call(env) status, header, _ = response log(env, status, header, began_at) response end private def log(env, status, header, began_at) ... end end
  82. class CommonLogger def initialize(app, logger=nil) @app = app @logger =

    logger end def call(env) began_at = Time.now response = @app.call(env) status, header, _ = response log(env, status, header, began_at) response end private def log(env, status, header, began_at) ... end end
  83. class CommonLogger def initialize(app, logger=nil) @app = app @logger =

    logger end def call(env) began_at = Time.now response = @app.call(env) status, header, _ = response log(env, status, header, began_at) response end private def log(env, status, header, began_at) ... end end
  84. class CommonLogger def initialize(app, logger=nil) @app = app @logger =

    logger end def call(env) began_at = Time.now response = @app.call(env) status, header, _ = response log(env, status, header, began_at) response end private def log(env, status, header, began_at) ... end end
  85. HttpKernel middlewares

  86. $app = new CallableHttpKernel(function ($request) { return new Response('Hello World!');

    });
  87. class Logger implements HttpKernelInterface { private $app; private $logger; public

    function __construct(HttpKernelInterface $app, LoggerInterface $logger) { $this->app = $app; $this->logger = $logger; } public function handle(Request $request, ...) { $response = $this->app->handle($request, $type, $catch); $this->log($request, $response); return $response; } private function log(Request $request, Response $response) { ... } }
  88. use Symfony\Component\HttpKernel\HttpCache\HttpCache; use Symfony\Component\HttpKernel\HttpCache\Store; $app = new HttpCache( $app, new

    Store(__DIR__.'/cache') );
  89. use Symfony\Component\HttpKernel\HttpCache\HttpCache; use Symfony\Component\HttpKernel\HttpCache\Store; $app = new HttpCache( $app, new

    Store(__DIR__.'/cache') ); use varnish!
  90. App Logger Authentication Session

  91. None
  92. CHH simensen igorw

  93. class Foo implements HttpKernelInterface { private $app; public function __construct(HttpKernelInterface

    $app) { $this->app = $app; } public function handle(Request $request, ...) { $response = $this->app->handle($request, $type, $catch); return $response; } } 1 2 3
  94. UrlMap $blog = new Silex\Application(); $blog->get('/', function () { return

    'This is the blog!'; }); $app = new Stack\UrlMap($app, [ '/blog' => $blog, ]);
  95. Session $app = new CallableHttpKernel(function ($request) { $session = $request->getSession();

    ... }); $app = new Stack\Session($app);
  96. OAuth $app = new Stack\OAuth($app, [ 'key' => 'foo', 'secret'

    => 'bar', 'callback_url' => 'http://localhost:8080/auth/verify', 'success_url' => '/', 'failure_url' => '/auth', ]); $app = new Stack\Session($app);
  97. OAuth $app = new CallableHttpKernel(function ($request) { $token = $request->attributes->get('oauth.token');

    if (!$token) { return new RedirectResponse('/auth'); } $params = $token->getExtraParams(); return sprintf('Welcome @%s!', $params['screen_name']); });
  98. Composition!

  99. $stack = (new Stack\Builder()) ->push('Stack\Session') ->push('Stack\OAuth', [...]) ->push('Foo'); $app =

    $stack->resolve($app);
  100. It doesn’t stop there

  101. • Authentication • Debug toolbar • Injected routes • Signed

    cookies • Asset management • Force SSL • Error handling
  102. Choose wisely

  103. Michael Rowe, from The Noun Project

  104. • joind.in/8666 • stackphp.com • @stackphp • @igorwesome • github.com/igorw/CgiHttpKernel