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

The HttpKernelInterface is a lie (tnphp)

Igor Wiedler
November 09, 2013

The HttpKernelInterface is a lie (tnphp)

Igor Wiedler

November 09, 2013
Tweet

More Decks by Igor Wiedler

Other Decks in Programming

Transcript

  1. the
    HttpKernelInterface
    is a lie

    View Slide

  2. @igorwesome

    View Slide

  3. View Slide

  4. “Interface”
    Protocol

    Communication

    Message passing

    View Slide

  5. Catherine Please, from The Noun Project

    View Slide

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

    View Slide

  7. hi!

    View Slide

  8. View Slide

  9. 10010101110100100

    View Slide

  10. 1001010111010010000110101
    Massimiliano Mauro, from The Noun Project

    View Slide

  11. Sergey Shmidt, from The Noun Project
    aloha!

    View Slide

  12. yay!

    View Slide

  13. 00101000011101100102

    View Slide

  14. View Slide

  15. View Slide

  16. View Slide

  17. View Slide

  18. Universal Interface

    View Slide

  19. View Slide

  20. 10010111001010001011

    View Slide

  21. 1234 4321

    View Slide

  22. foo
    bar
    baz
    foo
    baz
    Patrick n Hawaii, from The Noun Project

    View Slide

  23. foo moo
    Anuar Zhumaev, from The Noun Project

    View Slide

  24. find src -name '*.php' |

    grep -iv tests |

    cut -f2- -d/ |

    cut -f1 -d\. |

    awk '{ print length, $0 }' |

    sort -n |

    tr / \\ ;

    View Slide

  25. Tim Boelaars, from The Noun Project

    View Slide

  26. View Slide

  27. nc

    View Slide

  28. /\_/\
    / 0 0 \
    ====v====
    \ W /
    | | _
    / ___ \ /
    / / \ \ |
    (((-----)))-'
    /
    ( ___
    \__.=|___E
    /

    View Slide

  29. View Slide

  30. data
    Dmitry Baranovskiy, from The Noun Project

    View Slide

  31. xinetd

    View Slide

  32. View Slide

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

    View Slide

  34. /etc/xinet.d/fortune
    service fortune
    {
    disable = no
    socket_type = stream
    protocol = tcp
    user = xinetd
    wait = no
    server = /usr/local/bin/fortune
    }

    View Slide

  35. #!/bin/bash
    fortune | cowsay

    View Slide

  36. $ nc 7777

    View Slide

  37. $ nc 7777
    ______________________________________
    < Eat right, stay fit, and die anyway. >
    --------------------------------------
    \ ^__^
    \ (oo)\_______
    (__)\ )\/\
    ||----w |
    || ||

    View Slide

  38. /etc/xinet.d/cowsay
    service cowsay
    {
    disable = no
    socket_type = stream
    protocol = tcp
    user = xinetd
    wait = no
    server = /usr/games/cowsay
    }

    View Slide

  39. $ echo 'moo' | nc 7778

    View Slide

  40. #!/usr/bin/php
    !
    while (!feof(STDIN)) {
    echo transform(fgets(STDIN));
    }

    View Slide

  41. $ echo 'moo' | nc 7778
    _____
    < moo >
    -----
    \ ^__^
    \ (oo)\_______
    (__)\ )\/\
    ||----w |
    || ||

    View Slide

  42. cgi

    View Slide

  43. 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

    View Slide

  44. xinetd
    tcp http
    httpd

    View Slide

  45. http
    httpd script
    cgi

    View Slide

  46. script
    env vars
    data
    headers
    data

    View Slide

  47. GET / HTTP/1.1
    Host: igor.io
    Accept: */*
    REQUEST_METHOD = GET
    PATH_INFO = /
    HTTP_HOST = igor.io
    HTTP_ACCEPT = */*
    SERVER_NAME = igor.io

    View Slide

  48. Content-Type: text/html
    !


    ...

    View Slide

  49. fcgi

    View Slide

  50. script

    View Slide

  51. sockets are
    the new pipes

    View Slide

  52. • 1991: HTTP

    • 1993: CGI

    • 1995: PHP

    • 1996: FastCGI

    View Slide

  53. • 1997: Java Servlet

    • 2003: Python WSGI

    • 2007: Ruby Rack

    • 2009: Perl PSGI

    • 2011: Symfony2 HttpKernelInterface

    View Slide

  54. rack

    View Slide

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

    View Slide

  56. sapi

    View Slide

  57. $_SERVER
    header
    echo
    exit

    View Slide

  58. HttpKernelInterface

    View Slide

  59. interface HttpKernelInterface!
    {!
    /*** @return Response */!
    public function handle(Request $request);!
    }

    View Slide

  60. sapi
    kernel

    View Slide

  61. View Slide

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

    View Slide

  63. myths:
    !

    View Slide

  64. myths:
    caching

    View Slide

  65. myths:
    caching (use varnish)

    View Slide

  66. myths:
    caching (use varnish)
    functional tests

    View Slide

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

    View Slide

  68. kernel
    CGI

    View Slide

  69. kernel
    CGI
    anything!

    View Slide

  70. $kernel = new CgiHttpKernel(__DIR__.'/app');
    !
    $request = Request::create('/index.php');
    $response = $kernel->handle($request);
    !
    var_dump($response->getContent());

    View Slide

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

    View Slide

  72. caution: it’s slow
    (WIP: FcgiHttpKernel)

    View Slide

  73. Where is the value?

    View Slide

  74. REQ REP

    View Slide

  75. fcgi roles

    View Slide

  76. authorizer
    httpd
    responder
    filter

    View Slide

  77. rack
    middlewares

    View Slide

  78. HttpKernel
    middlewares

    View Slide

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

    View Slide

  80. 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)
    {
    ...
    }
    }

    View Slide

  81. $app = new Logger(
    $app,
    new Monolog\Logger()
    );

    View Slide

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

    View Slide

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

    View Slide

  84. App
    Logger
    Authentication
    Session

    View Slide

  85. View Slide

  86. do something before or
    after every request

    View Slide

  87. different take on
    event listeners

    View Slide

  88. 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

    View Slide

  89. UrlMap
    $blog = new Silex\Application();
    !
    $blog->get('/', function () {
    return 'This is the blog!';
    });
    !
    $app = new Stack\UrlMap($app, [
    '/blog' => $blog,
    ]);

    View Slide

  90. Session
    $app = new CallableHttpKernel(function ($request) {
    $session = $request->getSession();
    ...
    });
    !
    $app = new Stack\Session($app);

    View Slide

  91. OAuth
    $app = new Igorw\Stack\OAuth($app, [
    'key' => 'foo',
    'secret' => 'bar',
    'callback_url' => 'http://localhost:8080/auth/verify',
    'success_url' => '/',
    'failure_url' => '/auth',
    ]);
    !
    $app = new Stack\Session($app);

    View Slide

  92. OAuth
    $request->attributes->get('oauth.token');

    View Slide

  93. Composition!

    View Slide

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

    View Slide

  95. • GeoIp

    • IpRestrict

    • Backstage

    • Basic Authentication

    • Hawk

    • CORS
    Community

    View Slide

  96. It doesn’t stop there

    View Slide

  97. • Authentication

    • Debug toolbar

    • Injected routes

    • Signed cookies

    • Asset
    management

    • Force SSL

    • Error handling

    View Slide

  98. ( )

    View Slide

  99. Choose wisely

    View Slide

  100. Michael Rowe, from The Noun Project

    View Slide

  101. • joind.in/9990

    • stackphp.com

    • @stackphp

    • @igorwesome

    • github.com/igorw/CgiHttpKernel

    View Slide