D AV E Y S H A F I K
• Author of Zend PHP 5 Certification
Study Guide, Sitepoints PHP
Anthology: 101 Essential Tips, Tricks &
Hacks & PHP Master: Write Cutting
Edge Code
• A contributor to Zend Framework 1 &
2, phpdoc, & PHP internals
• Original creator of PHAR/
PHP_Archive
• @dshafik
R F C 7 5 4 0
H Y P E RT E XT T R A N S F E R P R OTO CO L V E RS I O N 2
Slide 9
Slide 9 text
R F C 7 5 4 1
H PA C K - H E A D E R CO M P R E SS I O N FO R H T T P/ 2
Slide 10
Slide 10 text
C R E AT E D BY I E T F H T T P W O R K I N G
G R O U P
C H A I R E D BY A K A M A I ' S M A R K N OT T I N G H A M
Slide 11
Slide 11 text
–J O H N N Y A P P L E S E E D
CC-BY:
1991 1996 1999
HTTP/0.9
HTTP/1.0
HTTP/1.1
2015
HTTP/2
2009
SPDY
Slide 12
Slide 12 text
B R O W S E R S U P P O RT
• Chrome + Chrome Mobile
• Firefox
• IE 11 on Windows 10
• MS Edge
• Safari (El Capitan/iOS 9)
• Opera
Slide 13
Slide 13 text
B I N A R Y I N ST E A D O F T E XT
CC-BY:
Slide 14
Slide 14 text
F U L LY M U LT I P L E X E D
CC-BY:
I N S T E A D O F O R D E R E D A N D B L O C K I N G
Slide 15
Slide 15 text
C A N US E O N E CO N N E CT I O N
FO R PA R A L L E L R E Q U E STS
CC-BY: Alosh Bennett
Slide 16
Slide 16 text
US E S H E A D E R CO M P R E SS I O N
CC-BY-SA:
R E D U C E S O V E R H E A D
Slide 17
Slide 17 text
S E R V E R P U S H
I S S U P E R CO O L ( N O R E A L LY )
CC-BY-SA:
Slide 18
Slide 18 text
S E R V E R P U S H
• Allows the server to proactively push assets like stylesheets and
images to the client without them needing to parse the HTML page
and make subsequent requests
• Done by pushing the assets into the client cache, avoiding the
roundtrip necessary to pull them up once the client makes the
request
Slide 19
Slide 19 text
W H AT D O E S H T T P/ 2 M E A N F O R M Y
A P P L I C AT I O N ?
Slide 20
Slide 20 text
T R A N S PA R E N T
CC-BY-SA:
H A N D L E D B Y N G I N X / A PA C H E
Slide 21
Slide 21 text
S O W H AT ’ S T H E P O I N T ?
Slide 22
Slide 22 text
H T T P/ 1 . X S U C K S
CC-BY: Flóra Soós
Slide 23
Slide 23 text
H T T P/ 1 . X S U C K S
• Minify + Concat JavaScript and CSS
• Inlining small JavaScript and CSS
• Using image sprites
• Using data: URIs
• Domain sharding
Slide 24
Slide 24 text
T H E S E T H I N G S A R E A L L " C L E V E R " H AC K S
CC-BY: Matt Biddulph
Slide 25
Slide 25 text
R E M E M B E R T H I S ?
CC-BY:
C A N US E O N E CO N N E CT I O N
FO R PA R A L L E L R E Q U E STS
Slide 26
Slide 26 text
U P LO A D I N G M U LT I P L E I M A G E S
CC-BY:
Slide 27
Slide 27 text
S E R I A L U P LO A D S
Ȑ
Slide 28
Slide 28 text
S E R I A L U P LO A D S
Ȑ
Slide 29
Slide 29 text
S E R I A L U P LO A D S
Ȑ
Slide 30
Slide 30 text
S E R I A L U P LO A D S
Ȑ
Slide 31
Slide 31 text
S E R I A L U P LO A D S
Ȑ
Slide 32
Slide 32 text
S E R I A L U P LO A D S
Ȑ
Slide 33
Slide 33 text
S E R I A L U P LO A D S
Ȑ
Slide 34
Slide 34 text
CO N CU R R E N T
Ȑ
Slide 35
Slide 35 text
CO N CU R R E N T
Ȑ
Slide 36
Slide 36 text
CO N CU R R E N T
Ȑ
Slide 37
Slide 37 text
CO N CU R R E N T
Ȑ
Slide 38
Slide 38 text
CO N CU R R E N T
Ȑ
Slide 39
Slide 39 text
A P I S
Slide 40
Slide 40 text
F E TC H I N G A B LO G P O ST + CO M M E N TS
CC-BY:
Slide 41
Slide 41 text
Ȑ
Slide 42
Slide 42 text
Ȑ
Slide 43
Slide 43 text
Ȑ
GET /post/1
Slide 44
Slide 44 text
Ȑ
GET /post/1
200 OK application/json
Slide 45
Slide 45 text
{
"type": "post",
"id": "1",
"title": "JSON API paints my bikeshed!",
"tags": ["json", "api", "relationships"],
"author": "http://example.com/posts/1/author",
"comments": "http://example.com/posts/1/comments"
}
M U LT I P L E X E D
Ȑ
GET /post/example/comments/3
Slide 63
Slide 63 text
M U LT I P L E X E D
Ȑ
GET /post/example/comments/3
GET /post/example/comments/1
Slide 64
Slide 64 text
M U LT I P L E X E D
Ȑ
GET /post/example/comments/3
GET /post/example/comments/1
GET /post/example/comments/2
Slide 65
Slide 65 text
M U LT I P L E X E D
Ȑ
GET /post/example/comments/3
GET /post/example/comments/1
GET /post/example/comments/2
200 OK application/json
Slide 66
Slide 66 text
M U LT I P L E X E D
Ȑ
GET /post/example/comments/3
GET /post/example/comments/1
GET /post/example/comments/2
200 OK application/json
200 OK application/json
Slide 67
Slide 67 text
M U LT I P L E X E D
Ȑ
GET /post/example/comments/3
GET /post/example/comments/1
GET /post/example/comments/2
200 OK application/json
200 OK application/json
200 OK application/json
Slide 68
Slide 68 text
CO D E
Slide 69
Slide 69 text
$numRequests = 378;
Slide 70
Slide 70 text
No content
Slide 71
Slide 71 text
H T T P/ 1 . 1 : SY N C H R O N O US
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, $i);
curl_exec($ch);
curl_close($ch);
}
Slide 72
Slide 72 text
H T T P/ 1 . 1 : SY N C H R O N O US
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, $i);
curl_exec($ch);
curl_close($ch);
}
Slide 73
Slide 73 text
H T T P/ 1 . 1 : SY N C H R O N O US
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, $i);
curl_exec($ch);
curl_close($ch);
}
Slide 74
Slide 74 text
H T T P/ 1 . 1 : SY N C H R O N O US
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, $i);
curl_exec($ch);
curl_close($ch);
}
Slide 75
Slide 75 text
H T T P/ 1 . 1 : SY N C H R O N O US
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, $i);
curl_exec($ch);
curl_close($ch);
}
Slide 76
Slide 76 text
4 7 . 6 7
s e co n d s
CC-BY:
Slide 77
Slide 77 text
H T T P/ 2 : SY N C H R O N O US
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, $i);
curl_setopt($ch, CURLOPT_HTTP_VERSION, HTTP_VERSION_2_0);
curl_exec($ch);
curl_close($ch);
}
Slide 78
Slide 78 text
H T T P/ 2 : SY N C H R O N O US
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, $i);
curl_setopt($ch, CURLOPT_HTTP_VERSION, HTTP_VERSION_2_0);
curl_exec($ch);
curl_close($ch);
}
Slide 79
Slide 79 text
6 2 . 1 9
s e co n d s
CC-BY-NC:
Slide 80
Slide 80 text
$mh = curl_multi_init();
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$handles[] = $ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, ‘%d');
curl_multi_add_handle($mh, $ch);
}
H T T P/ 1 . 1 : CO N CU R R E N T
Slide 81
Slide 81 text
$mh = curl_multi_init();
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$handles[] = $ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, ‘%d');
curl_multi_add_handle($mh, $ch);
}
H T T P/ 1 . 1 : CO N CU R R E N T
Slide 82
Slide 82 text
$mh = curl_multi_init();
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$handles[] = $ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, ‘%d');
curl_multi_add_handle($mh, $ch);
}
H T T P/ 1 . 1 : CO N CU R R E N T
Slide 83
Slide 83 text
$mh = curl_multi_init();
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$handles[] = $ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, ‘%d');
curl_multi_add_handle($mh, $ch);
}
H T T P/ 1 . 1 : CO N CU R R E N T
Slide 84
Slide 84 text
H T T P/ 1 . 1 : CO N CU R R E N T ( CO N T. )
do {
$exec = curl_multi_exec($mh, $running);
} while ($exec == CURLM_CALL_MULTI_PERFORM);
while ($running && $exec == CURLM_OK) {
$ready = curl_multi_select($mh);
if ($ready != -1) {
do {
$exec = curl_multi_exec($mh, $running);
} while ($exec == CURLM_CALL_MULTI_PERFORM);
}
}
Slide 85
Slide 85 text
8 . 6 6
s e co n d s
Slide 86
Slide 86 text
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$handles[] = $ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, ‘%d');
curl_multi_add_handle($mh, $ch);
}
H T T P/ 2 : M U LT I P L E X E D
$mh = curl_multi_init();
Slide 87
Slide 87 text
$url = 'https://http2.akamai.com/demo/tile-%d.png';
for ($i = 0; $i <= $numRequests; $i++) {
$handles[] = $ch = curl_init();
$conf[CURLOPT_URL] = sprintf($url, ‘%d');
curl_multi_add_handle($mh, $ch);
}
H T T P/ 2 : M U LT I P L E X E D
curl_multi_setopt($mh,
CURLMOPT_PIPELINING,
CURLPIPE_MULTIPLEX
);
$mh = curl_multi_init();
Slide 88
Slide 88 text
H T T P/ 2 : M U LT I P L E X E D ( CO N T. )
do {
$exec = curl_multi_exec($mh, $running);
} while ($exec == CURLM_CALL_MULTI_PERFORM);
while ($running && $exec == CURLM_OK) {
$ready = curl_multi_select($mh);
if ($ready != -1) {
do {
$exec = curl_multi_exec($mh, $running);
} while ($exec == CURLM_CALL_MULTI_PERFORM);
}
}
Slide 89
Slide 89 text
2 . 1 4
s e co n d s
CC-BY:
Slide 90
Slide 90 text
H T T P/ 2 N E G OT I AT I O N
CC-BY-ND:
Slide 91
Slide 91 text
P R OTO CO L I D E N T I F I E RS
• h2 — HTTP/2 over TLS, negotiated via ALPN (Application-Layer
Protocol Negotiation)
• h2c — HTTP/2 over TCP (plain text), uses an HTTP/1.1 request with
a 101 Switching Protocols status response if supported
Slide 92
Slide 92 text
– W I K I P E D I A /A P P L I C AT I O N - L AY E R _ P R OTO CO L _ N E G OT I AT I O N
Application-Layer Protocol Negotiation (ALPN) is a Transport Layer
Security (TLS) extension for application layer protocol negotiation. ALPN
allows the application layer to negotiate which protocol should be
performed over a secure connection in a manner which avoids additional
round trips and which is independent of the application layer protocols. It
is used by HTTP/2. […] On July 11, 2014, ALPN was published as RFC 7301
Slide 93
Slide 93 text
H 2 C U P G R A D E N E G OT I AT I O N
> GET / HTTP/1.1
> Host: server.example.com
> Connection: Upgrade, HTTP2-Settings
> Upgrade: h2c
> HTTP2-Settings:
< HTTP/1.1 101 Switching Protocols
< Connection: Upgrade
< Upgrade: h2c
<
< [ HTTP/2 connection ...
Slide 94
Slide 94 text
H 2 C U P G R A D E N E G OT I AT I O N ( CO N T. )
• May be an OPTIONS request if concurrency of multiple requests is
important
• May be any request type (e.g. PUT/POST/GET/HEAD/DELETE) but
any body must be sent in it's entirety before HTTP/2 can start
• A server must ignore an "h2" token in an Upgrade header field.
Presence of a token with "h2" implies HTTP/2 over TLS, which is
instead negotiated via TLS-ALPN
• It must include a settings payload with the initial request
Slide 95
Slide 95 text
A L L B R O W S E RS R E Q U I R E T LS FO R H T T P/ 2
CC-BY: Jason Baker
Slide 96
Slide 96 text
D I R E CT CO N N E CT W I T H H T T P/ 2
Slide 97
Slide 97 text
P R I O R K N O W L E D G E
• It is possible to set up a connection with HTTP/1.1 or ALPN
negotiation when prior knowledge of HTTP/2 is known
• Performance enhancement
• Client/Server must send the HTTP/2 connection prefix
• Not supported in curl yet
Slide 98
Slide 98 text
S E R V E R P US H
CC-BY:
Slide 99
Slide 99 text
Ȑ
Slide 100
Slide 100 text
Ȑ
Slide 101
Slide 101 text
Ȑ
GET /post/1
Slide 102
Slide 102 text
Ȑ
GET /post/1
200 OK application/json
Slide 103
Slide 103 text
GET /post/1/comments
Ȑ
GET /post/1
200 OK application/json
Slide 104
Slide 104 text
GET /post/1/comments
GET /post/1/comment/1
Ȑ
GET /post/1
200 OK application/json
Slide 105
Slide 105 text
Ȑ
GET /post/1/comments
GET /post/1/comment/1
Slide 106
Slide 106 text
Ȑ
GET /post/1/comment/2
GET /post/1/comment/3
GET /post/1/comment/4
GET /post/1/comments
GET /post/1/comment/1
Slide 107
Slide 107 text
Ȑ
GET /post/1/comment/2
GET /post/1/comment/3
GET /post/1/comment/4
GET /post/1/comment/1/author
GET /post/1/comment/2/author
GET /post/1/comment/3/author
GET /post/1/comment/4/author
GET /post/1/comments
GET /post/1/comment/1
Slide 108
Slide 108 text
Ȑ
GET /post/1/comment/2
GET /post/1/comment/3
GET /post/1/comment/4
GET /post/1/comment/1/author
GET /post/1/comment/2/author
GET /post/1/comment/3/author
GET /post/1/comment/4/author
GET /post/1/comment/1/author/avatar.png
GET /post/1/comment/2/author/avatar.png
GET /post/1/comment/3/author/avatar.png
GET /post/1/comment/4/author/avatar.png
GET /post/1/comments
GET /post/1/comment/1
Slide 109
Slide 109 text
CSS /J S M I N I F I C AT I O N I S U N E C E SS A R Y
CC-BY:
G Z I P CO M P R E SS I O N + M U LT I P L E X I N G + S E R V E R P US H
Slide 110
Slide 110 text
ST R E A M S
CC-BY: Kylir Horton
Slide 111
Slide 111 text
ST R E A M S
• Each request/response is a stream
• Streams are comprised of Frames
• Streams may have a weight (1-256)
• Streams may have a dependency
Slide 112
Slide 112 text
ST R E A M W E I G H TS
Stream A
Weight: 1
Stream B
Weight: 2
Stream C
Weight: 3
2X Stream A 1.5X Stream B
3X Stream A
Slide 113
Slide 113 text
ST R E A M D E P E N D E N C I E S
Stream A
Stream B
Depends: A
Stream C
Depends: B
Delivered after A Delivered after B
Slide 114
Slide 114 text
F R A M E S
CC-BY: Bart Everson
Slide 115
Slide 115 text
F R A M E S
• Messages are composed of multiple frames, e.g. headers, data,
and settings
• Each frame has a common header
• 9 byte, length prefixed
• Easy & efficient to parse
• Frames can be interleaved — this is multiplexing
Slide 116
Slide 116 text
F R A M E S
POST /search HTTP/1.1
Host: example.org
Content-Type: application/json
Content-Length: 58
{
"keywords":"example",
"location":"posts"
}
HEADERS
frame
Data
frame
}
}
Slide 117
Slide 117 text
H E A D E RS : H PAC K
CC-BY-SA:
Slide 118
Slide 118 text
H E A D E RS : H PA C K
• Uses a table of known values as an index
• Can represent a header name and value (e.g. :status: 404), or
just a header name (e.g. accept:)
• Values are either statically encoded, or use a static Huffman code
A KA M A I { O P E N } E D G E G R I D F O R P H P
Slide 121
Slide 121 text
W E US E G U ZZ L E
Slide 122
Slide 122 text
G U ZZ L E S U P P O RT
• Some support
• Doesn’t handle lack of http2 support in libcurl
• Doesn’t handle multiplexing
• Untested (but should be OK, as libcurl itself is tested)
• Details: http://daveyshafik.com/guzzle-http2
Slide 123
Slide 123 text
CO D E
CC-BY:
Slide 124
Slide 124 text
H T T P/ 1 . 1 : SY N C H R O N O US
use GuzzleHttp\Client;
$url = 'https://http2.akamai.com/demo/tile-%d.png';
$client = new Client();
for ($i = 0; $i <= $numRequests; $i++) {
$client->get(sprintf($url, $i));
}
Slide 125
Slide 125 text
H T T P/ 1 . 1 : SY N C H R O N O US
use GuzzleHttp\Client;
$url = 'https://http2.akamai.com/demo/tile-%d.png';
$client = new Client();
for ($i = 0; $i <= $numRequests; $i++) {
$client->get(sprintf($url, $i));
}
Slide 126
Slide 126 text
H T T P/ 1 . 1 : SY N C H R O N O US
use GuzzleHttp\Client;
$url = 'https://http2.akamai.com/demo/tile-%d.png';
$client = new Client();
for ($i = 0; $i <= $numRequests; $i++) {
$client->get(sprintf($url, $i));
}
Slide 127
Slide 127 text
H T T P/ 1 . 1 : SY N C H R O N O US
use GuzzleHttp\Client;
$url = 'https://http2.akamai.com/demo/tile-%d.png';
$client = new Client();
for ($i = 0; $i <= $numRequests; $i++) {
$client->getAsync(sprintf($url, $i));
}
$results = Promise\unwrap($promises);
Slide 128
Slide 128 text
H T T P/ 1 . 1 : SY N C H R O N O US
use GuzzleHttp\Client;
$url = 'https://http2.akamai.com/demo/tile-%d.png';
$client = new Client();
for ($i = 0; $i <= $numRequests; $i++) {
$client->getAsync(sprintf($url, $i));
}
$results = Promise\unwrap($promises);
Slide 129
Slide 129 text
H T T P/ 1 . 1 : SY N C H R O N O US
use GuzzleHttp\Client;
$url = 'https://http2.akamai.com/demo/tile-%d.png';
$client = new Client();
for ($i = 0; $i <= $numRequests; $i++) {
$client->getAsync(sprintf($url, $i));
}
$results = Promise\unwrap($promises);
Slide 130
Slide 130 text
use GuzzleHttp\Client;
$url = 'https://http2.akamai.com/demo/tile-%d.png';
$client = new Client(
for ($i = 0; $i <= $numRequests; $i++) {
$client->get(sprintf($url, $i));
}
H T T P/ 2 . 0 : SY N C H R O N O US
);
Slide 131
Slide 131 text
use GuzzleHttp\Client;
$url = 'https://http2.akamai.com/demo/tile-%d.png';
$client = new Client(
for ($i = 0; $i <= $numRequests; $i++) {
$client->get(sprintf($url, $i));
}
['version' => 2]
H T T P/ 2 . 0 : SY N C H R O N O US
);
Slide 132
Slide 132 text
H T T P/ 2 : M U LT I P L E X E D
use GuzzleHttp\Client;
$url = 'https://http2.akamai.com/demo/tile-%d.png';
$client = new Client(['version' => 2]);
for ($i = 0; $i <= $numRequests; $i++) {
$client->getAsync(sprintf($url, $i));
}
$results = Promise\unwrap($promises);
Slide 133
Slide 133 text
H T T P/ 1 . 1 : CO N CU R R E N T U P LOA D S
use \Akamai\NetStorage\Handler\Authentication as AuthHandler;
use \Akamai\NetStorage\Authentication;
$stack = \GuzzleHttp\HandlerStack::create();
$handler = new AuthHandler();
$handler->setSigner(
(new Authentication())->setKey($key, $keyName)
);
$client = new Akamai\Edgegrid\Open\Client([
'handler' => $stack
]);
Slide 134
Slide 134 text
$url = "http://example.akamaihd.net/cpCode/%s";
foreach ($_FILES as $file) {
$fileName = Ramsey\Uuid\Uuid::uuid4();
$promises = $client->putAsync(
sprintf($url, $filename),
[
'body' => fopen($file['tmp_name'], 'r+')
]
);
}
$results = Promise\unwrap($promises);
H T T P/ 2 : M U LT I P L E X E D F I L E U P LO A D ( CO N T. )
Slide 135
Slide 135 text
$url = "http://example.akamaihd.net/cpCode/%s";
foreach ($_FILES as $file) {
$fileName = Ramsey\Uuid\Uuid::uuid4();
$promises = $client->putAsync(
sprintf($url, $filename),
[
'body' => fopen($file['tmp_name'], 'r+')
]
);
}
$results = Promise\unwrap($promises);
H T T P/ 2 : M U LT I P L E X E D F I L E U P LO A D ( CO N T. )
Slide 136
Slide 136 text
$url = "http://example.akamaihd.net/cpCode/%s";
foreach ($_FILES as $file) {
$fileName = Ramsey\Uuid\Uuid::uuid4();
$promises = $client->putAsync(
sprintf($url, $filename),
[
'body' => fopen($file['tmp_name'], 'r+')
]
);
}
$results = Promise\unwrap($promises);
H T T P/ 2 : M U LT I P L E X E D F I L E U P LO A D ( CO N T. )
Slide 137
Slide 137 text
$url = "http://example.akamaihd.net/cpCode/%s";
foreach ($_FILES as $file) {
$fileName = Ramsey\Uuid\Uuid::uuid4();
$promises = $client->putAsync(
sprintf($url, $filename),
[
'body' => fopen($file['tmp_name'], 'r+')
]
);
}
$results = Promise\unwrap($promises);
H T T P/ 2 : M U LT I P L E X E D F I L E U P LO A D ( CO N T. )
Slide 138
Slide 138 text
$url = "http://example.akamaihd.net/cpCode/%s";
foreach ($_FILES as $file) {
$fileName = Ramsey\Uuid\Uuid::uuid4();
$promises = $client->putAsync(
sprintf($url, $filename),
[
'body' => fopen($file['tmp_name'], 'r+')
]
);
}
$results = Promise\unwrap($promises);
H T T P/ 2 : M U LT I P L E X E D F I L E U P LO A D ( CO N T. )
Slide 139
Slide 139 text
H T T P/ 2 : M U LT I P L E X E D F I L E U P LO A D ( P O S S I B L E A P I )
use \Akamai\NetStorage\Handler\Authentication as AuthHandler;
use \Akamai\NetStorage\Authentication;
$stack = \GuzzleHttp\HandlerStack::create();
$handler = new AuthHandler();
$handler->setSigner(
(new Authentication())->setKey($key, $keyName)
);
$client = new Akamai\Edgegrid\Open\Client([
'handler' => $stack,
'version' => 2
]);
Slide 140
Slide 140 text
H T T P/ 2 : M U LT I P L E X E D F I L E U P LO A D ( P O S S I B L E A P I )
use \Akamai\NetStorage\Handler\Authentication as AuthHandler;
use \Akamai\NetStorage\Authentication;
$stack = \GuzzleHttp\HandlerStack::create();
$handler = new AuthHandler();
$handler->setSigner(
(new Authentication())->setKey($key, $keyName)
);
$client = new Akamai\Edgegrid\Open\Client([
'handler' => $stack,
'version' => 2
]);
Slide 141
Slide 141 text
$url = "http://example.akamaihd.net/cpCode/%s";
foreach ($_FILES as $file) {
$fileName = Ramsey\Uuid\Uuid::uuid4();
$promises = $client->putAsync(
sprintf($url, $filename),
[
'body' => fopen($file['tmp_name'], 'r+')
]
);
}
$results = Promise\unwrap($promises);
H T T P/ 2 : M U LT I P L E X E D F I L E U P LO A D ( CO N T. )
Slide 142
Slide 142 text
R FC : CU R L H T T P/ 2 P US H S U P P O RT
https://daveyshafik.com/curl-http2-push
Slide 143
Slide 143 text
I N S U M M A R Y
Slide 144
Slide 144 text
N O M O R E H AC K S !
Slide 145
Slide 145 text
H U G E P E R FO R M A N C E W I N S
Slide 146
Slide 146 text
6 0 % + M A R K E T S H A R E
Slide 147
Slide 147 text
H T T P / 2 I S A W E S O M E !
CC-BY-SA:
Slide 148
Slide 148 text
F E E D B A C K & Q U E S T I O N S
Twitter:
Email:
Slides:
@dshafik
[email protected]
http://daveyshafik.com/slides