Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
The HttpKernelInterface is a lie
Search
Igor Wiedler
May 23, 2013
Programming
2.6k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
The HttpKernelInterface is a lie
Igor Wiedler
May 23, 2013
More Decks by Igor Wiedler
See All by Igor Wiedler
Redis Bedtime Stories
igorw
1
390
Wide Event Analytics (LISA19)
igorw
4
960
a day in the life of a request
igorw
0
180
production: an owner's manual
igorw
0
210
The Power of 2
igorw
0
360
LISP 1.5 Programmer's Manual: A Dramatic Reading
igorw
0
500
The Moral Character of Software
igorw
1
340
interdisciplinary computing (domcode)
igorw
0
330
miniKanren (clojure berlin)
igorw
1
350
Other Decks in Programming
See All in Programming
あなたの await、OS まで届いてる? strace で覗く JavaScript の非同期
hasutosasaki
1
1.3k
GemmaをJevのように使ってみる / Use Gemma like Jev
kishida
5
830
SalesForceを内製化!? ~ HR事業を支える顧客管理基盤のインフラを大公開 ~
oku053
0
200
Python Lambdaにおけるテストしやすい設計とAI支援の活用 / Designing Testable Python Lambda Functions with AI
kitano_yuichi
1
130
Groovy as a human and AI friendly programming language
paulk
0
110
dotNET_vulnclicker_intro.pdf
deka_morita
0
150
JIS keyboard support in Omarchy
lef237
0
160
Domain-Driven Transformation
hschwentner
2
2.3k
AmebaブログはKMPから卒業します
kmars0605
0
220
学びを記事・スライド・Xへ高速展開する― AI-assisted Learning Loopで回すコンテンツ生成術
ochtum
0
130
[JA] Domain Modeling with Vanilla Rails: 「操作」から再考するRailsの設計論
yasaichi
4
850
AI時代のTerminal環境を UNIX哲学で設計・運用する
yasunori0418
1
210
Featured
See All Featured
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
950
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
580
Crafting Experiences
bethany
1
390
Side Projects
sachag
456
43k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
310
Fantastic passwords and where to find them - at NoRuKo
philnash
53
4k
Discover your Explorer Soul
emna__ayadi
2
1.3k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
2
330
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Skip the Path - Find Your Career Trail
mkilby
1
260
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
74
43k
Transcript
the HttpKernelInterface is a lie
@igorwesome
None
“Interface” Protocol Communication Message passing
Catherine Please, from The Noun Project
Paulo Sá Ferreira - Purple Matter, from The Noun Project
hi!
None
10010101110100100
1001010111010010000110101 Massimiliano Mauro, from The Noun Project
Sergey Shmidt, from The Noun Project aloha!
yay!
00101000011101100102
None
None
None
None
None
10010111001010001011
1234 4321
foo bar baz foo baz Patrick n Hawaii, from The
Noun Project
foo moo Anuar Zhumaev, from The Noun Project
find src -name '*.php' | grep -iv tests | cut
-f2- -d/ | cut -f1 -d\. | awk '{ print length, $0 }' | sort -n | tr / \\ ;
Tim Boelaars, from The Noun Project
None
nc
/\_/\ / 0 0 \ ====v==== \ W / |
| _ / ___ \ / / / \ \ | (((-----)))-' / ( ___ \__.=|___E /
None
data Dmitry Baranovskiy, from The Noun Project
xinetd
None
/etc/xinet.d/<service> service <service> { disable = no socket_type = stream
protocol = tcp user = <user> wait = no server = /usr/local/bin/<program> }
/etc/xinet.d/fortune service fortune { disable = no socket_type = stream
protocol = tcp user = xinetd wait = no server = /usr/local/bin/fortune }
#!/bin/bash fortune | cowsay
$ nc <host> 7777
$ nc <host> 7777 ______________________________________ < Eat right, stay fit,
and die anyway. > -------------------------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
/etc/xinet.d/cowsay service cowsay { disable = no socket_type = stream
protocol = tcp user = xinetd wait = no server = /usr/games/cowsay }
$ echo 'moo' | nc <host> 7778
$ echo 'moo' | nc <host> 7778 _____ < moo
> ----- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
#!/usr/bin/php <?php while (!feof(STDIN)) { echo transform(fgets(STDIN)); }
cgi
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
xinetd tcp http httpd
http httpd script cgi
script env vars data headers data
GET / HTTP/1.1 Host: igor.io Accept: */* REQUEST_METHOD = GET
PATH_INFO = / HTTP_HOST = igor.io HTTP_ACCEPT = */* SERVER_NAME = igor.io =>
Content-Type: text/html <!DOCTYPE html> <html> ... </html>
curl => inetd | web | cgi
fcgi
script
sockets are the new pipes
• 1991: HTTP • 1993: CGI • 1995: PHP •
1996: FastCGI
• 1997: Java Servlet • 2003: Python WSGI • 2007:
Ruby Rack • 2009: Perl PSGI • 2011: Symfony2 HttpKernelInterface
rack
class HelloWorld def call(env) [ 200, {"Content-Type" => "text/plain"}, ["Hello
world!"] ] end end
function helloWorld(array $env) { return [ 200, ["Content-Type" => "text/plain"],
["Hello world!"], ]; }
sapi
$_SERVER header echo exit
HttpKernelInterface
sapi kernel
tcp websocket HTTP/1.1 <soap> {“JSON”}
“legacy” apps: it’s all great until exit;
myths:
myths: caching
myths: caching (use varnish)
myths: caching (use varnish) functional tests
CgiHttpKernel adapter from kernel to cgi functional test “legacy” apps
kernel CGI
kernel CGI anything!
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
$kernel = new CgiHttpKernel(__DIR__.'/app'); $request = Request::create('/index.php'); $response = $kernel->handle($request);
var_dump($response->getContent());
use Symfony\Component\HttpKernel\Client; $client = new Client($kernel); $crawler = $client->request('GET', '/index.php');
caution: it’s slow (but could be optimized)
Where is the value?
REQ REP
fcgi roles
authorizer httpd responder filter
rack middlewares
class EmptyDecorator def initialize(app) @app = app end def call(env)
@app.call(env) end end
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
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
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
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
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
HttpKernel middlewares
$app = new CallableHttpKernel(function ($request) { return new Response('Hello World!');
});
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) { ... } }
use Symfony\Component\HttpKernel\HttpCache\HttpCache; use Symfony\Component\HttpKernel\HttpCache\Store; $app = new HttpCache( $app, new
Store(__DIR__.'/cache') );
use Symfony\Component\HttpKernel\HttpCache\HttpCache; use Symfony\Component\HttpKernel\HttpCache\Store; $app = new HttpCache( $app, new
Store(__DIR__.'/cache') ); use varnish!
App Logger Authentication Session
None
CHH simensen igorw
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
UrlMap $blog = new Silex\Application(); $blog->get('/', function () { return
'This is the blog!'; }); $app = new Stack\UrlMap($app, [ '/blog' => $blog, ]);
Session $app = new CallableHttpKernel(function ($request) { $session = $request->getSession();
... }); $app = new Stack\Session($app);
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);
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']); });
Composition!
$stack = (new Stack\Builder()) ->push('Stack\Session') ->push('Stack\OAuth', [...]) ->push('Foo'); $app =
$stack->resolve($app);
It doesn’t stop there
• Authentication • Debug toolbar • Injected routes • Signed
cookies • Asset management • Force SSL • Error handling
Choose wisely
Michael Rowe, from The Noun Project
• joind.in/8666 • stackphp.com • @stackphp • @igorwesome • github.com/igorw/CgiHttpKernel