Slide 1

Slide 1 text

HttpFoundation An excursion in a Symfony2 component

Slide 2

Slide 2 text

Who am I • Magnus Nordlander • Developer at E-butik.se • ~6 years of Symfony experience • SensioLabs Certified Symfony Developer

Slide 3

Slide 3 text

“HttpFoundation defines an object- oriented layer for the HTTP specification.”

Slide 4

Slide 4 text

HTTP

Slide 5

Slide 5 text

HTTP • Created by Tim Berners-Lee back in ’91 • Current version is HTTP 1.1, standardized in ’99 in IETF RFC 2616 • Single best advice: You work with HTTP every day. Read RFC 2616.

Slide 6

Slide 6 text

An HTTP request/response GET /foo/baz HTTP/1.1 Host: www.example.com HTTP/1.1 200 OK Date: Mon, 18 Feb 2013 20:38:34 GMT Content-Length: 12 Content-Type: text/plain Connection: close Hello world!

Slide 7

Slide 7 text

Another request/response POST /?foo=quux HTTP/1.1 Host: www.example.com Content-Type: application/x-www-form- urlencoded Content-Length: 9 bar=xyzzy HTTP/1.1 200 OK Content-Length: 21 Content-Type: text/plain Connection: close Foo: quux, Bar: xyzzy

Slide 8

Slide 8 text

Another request/response POST /?foo=quux HTTP/1.1 Host: www.example.com Content-Type: application/x-www-form- urlencoded Content-Length: 9 bar=xyzzy HTTP/1.1 200 OK Content-Length: 21 Content-Type: text/plain Connection: close Foo: quux, Bar: xyzzy Symfony\Component\HttpFoundation\Request Symfony\Component\HttpFoundation\Response

Slide 9

Slide 9 text

As code… query->get(‘foo’); $bar = $request->request->get(‘bar’); $response = new Response( 200, sprintf(“Foo: %s, Bar: %s”, $foo, $bar), [‘Content-Type’ => ‘text/plain’]); $response->send();

Slide 10

Slide 10 text

This just looks like more code? Is it worth it?

Slide 11

Slide 11 text

Yes

Slide 12

Slide 12 text

Let’s look at the code query->get(‘foo’); $bar = $request->request->get(‘foo’); $response = new Response(200, sprintf(“Foo: %s, Bar: %s”, $foo, $bar)); $response->send();

Slide 13

Slide 13 text

Let’s look at the code query->get(‘foo’); $bar = $request->request->get(‘foo’); $response = new Response(200, sprintf(“Foo: %s, Bar: %s”, $foo, $bar)); $response->send(); Encapsulating the superglobals: great for testing, reduces hidden dependencies

Slide 14

Slide 14 text

Let’s look at the code query->get(‘foo’); $bar = $request->request->get(‘foo’); $response = new Response(200, sprintf(“Foo: %s, Bar: %s”, $foo, $bar)); $response->send(); Because these come from an object, easily fakable in tests. Additional features like default values, fetching by path.

Slide 15

Slide 15 text

Let’s look at the code query->get(‘foo’); $bar = $request->request->get(‘foo’); $response = new Response(200, sprintf(“Foo: %s, Bar: %s”, $foo, $bar)); $response->send(); Entire response encapsulated: Great for functional tests. No output (nor headers) until send. Processable by listener, middleware etc.

Slide 16

Slide 16 text

Edge case handling

Slide 17

Slide 17 text

Edge case handling • One word: Proxy • Requests through proxies originate through the proxy IP • Most send the X-Forwarded-For header, with the client IP • And yes, you want proxy support (for performance reasons)

Slide 18

Slide 18 text

Edge case handling

Slide 19

Slide 19 text

Edge case handling • Now we have a security flaw • Any client can send the X-Forwarded-For header, spoofing its IP • Only trusted proxies should be allowed to do that

Slide 20

Slide 20 text

Edge case handling

Slide 21

Slide 21 text

Edge case handling • That’s not quite it though... • You can have multiple upstream proxies, and they send a comma separated list of IP addresses. • Also, not all proxies use X-Forwarded-For, because that’s never been standardized • Are you getting a headache yet? Let’s look at how to do it with HttpFoundation instead.

Slide 22

Slide 22 text

Edge case handling getClientIp();

Slide 23

Slide 23 text

Edge case handling • X-Forwarded-Host, X-Forwarded-Proto, X-Forwarded-Port • X-Http-Method-Override • Accept headers with quality • Non-standard request content types

Slide 24

Slide 24 text

Are you convinced?

Slide 25

Slide 25 text

The Request class • Can be created from Superglobals, or manually • HTTP based, not CGI based • HTTP based methods and properties

Slide 26

Slide 26 text

The Request class • Important ParameterBags • query • request • headers • attributes

Slide 27

Slide 27 text

The Request class • Assorted methods • getMethod • getContent($asResource = false) • getRequestFormat

Slide 28

Slide 28 text

The Response class • Also HTTP based • Common HTTP Header “clusters” have specific methods, e.g. caching • public function __construct($content = '', $status = 200, $headers = [])

Slide 29

Slide 29 text

Parameter bags • Like PHP arrays, but better • Defaults handling • Deep get syntax • Specialized subclasses like HeaderBag and ServerBag

Slide 30

Slide 30 text

What else is there? • HTTP caching support (expiration and validation) • Sessions • Storage abstraction • Flash parameters • Cookies

Slide 31

Slide 31 text

What else is there? • Uploaded file handling • Streamed responses • Accept header parsing

Slide 32

Slide 32 text

HttpKernelInterface • Housed in the HttpKernel component • One of the most important interfaces in the Symfony2 ecosystem • public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true); • Returns Response

Slide 33

Slide 33 text

HttpKernelInterface • Foundation for the Request/Response paradigm of Symfony2 • Because of this interface, all web stacks implementing HttpKernelInterface is inherently compatible!

Slide 34

Slide 34 text

Getting HttpFoundation • Composer (symfony/http-foundation) • Github (github.com/symfony/HttpFoundation)

Slide 35

Slide 35 text

Learn more! • Symfony.com • Middlewares with HttpKernel: https://igor.io/2013/02/02/http-kernel- middlewares.html • Read RFC2616: http://www.w3.org/Protocols/rfc2616/rfc2616.html