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

[Edge 2016] HTTP/2 and Asynchronous APIs

[Edge 2016] HTTP/2 and Asynchronous APIs

HTTP/2 (H2) is coming, and along with it a whole new way of communicating over the web. Connection re-use, prioritization, multiplexing, and server push are just some of the features in H2.

In this talk we'll look at how to handle HTTP/2 Server Push programmatically, and how it can affect your application architecture.

Davey Shafik

October 19, 2016
Tweet

More Decks by Davey Shafik

Other Decks in Programming

Transcript

  1. H T T P/ 2 A N D A SY N C H R O N O U S A P I S

    View Slide

  2. F E TC H I N G A B LO G P O ST + CO M M E N TS
    CC-BY: John Trainor

    View Slide

  3. Ȑ

    View Slide

  4. Ȑ

    View Slide

  5. Ȑ
    GET /post/1

    View Slide

  6. Ȑ
    GET /post/1
    200 OK application/json

    View Slide

  7. {
    "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"
    }

    View Slide

  8. {
    "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"
    }

    View Slide

  9. Ȑ

    View Slide

  10. Ȑ

    View Slide

  11. Ȑ
    GET /posts/1/comments

    View Slide

  12. Ȑ
    GET /posts/1/comments
    200 OK application/json

    View Slide

  13. [
    "http://example.org/post/1/comment/1",
    "http://example.org/post/1/comment/2",
    "http://example.org/post/1/comment/3",
    "http://example.org/post/1/comment/4"
    ]

    View Slide

  14. Ȑ

    View Slide

  15. Ȑ

    View Slide

  16. Ȑ
    GET /post/example/comments/1

    View Slide

  17. Ȑ
    GET /post/example/comments/
    200 OK application/json
    1

    View Slide

  18. 2
    Ȑ
    GET /post/example/comments/
    200 OK application/json
    1

    View Slide

  19. 2
    3
    Ȑ
    GET /post/example/comments/
    200 OK application/json
    1

    View Slide

  20. 2
    3
    4
    Ȑ
    GET /post/example/comments/
    200 OK application/json
    1

    View Slide

  21. {
    "type": "comment",
    "id": "1",
    "title": "FIRST!",
    "author": "http://example.com/post/1/comment/1/author"
    }

    View Slide

  22. 6
    requests
    (possibly connections)

    View Slide

  23. 14
    requests
    (possibly connections)

    View Slide

  24. L E T ’ S M U LT I P L E X !

    View Slide

  25. M U LT I P L E X E D
    Ȑ

    View Slide

  26. M U LT I P L E X E D
    Ȑ
    GET /post/example/comments/3

    View Slide

  27. M U LT I P L E X E D
    Ȑ
    GET /post/example/comments/3
    GET /post/example/comments/1

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  32. S T I L L M A K I N G L O T S O F R E Q U E S T S

    View Slide

  33. D E P E N D E N C I E S

    View Slide

  34. {
    "type": "post",
    "id": "1",
    "title": "JSON API paints my bikeshed!",
    "tags": ["json", "api", "relationships"],
    "author": {
    "type": "author",
    "id": 1,
    "name": "Davey Shafik",
    "twitter": "@dshafik",
    "gravatar": "fee39f0c0ffb29d9ac21607ed188be6b"
    },
    "comments": [
    {
    "type": "comment",
    "id": "1",
    "content": "FIRST!",
    "author": {
    "type": "author",
    "id": 2,
    "name": "Jill Random",
    "gravatar": "706b16b2fb732ab6079a10fea61d078b"
    }
    },
    {
    "type": "comment",
    "id": "2",
    "content": "second",
    "author": {
    "type": "author",
    "id": 3,
    "name": "John Person",
    "gravatar": "8e2279479945ca4778eb3cb8d88cda58"
    }
    },
    {
    "type": "comment",
    "id": "3",
    "content": "third",
    "author": {
    "type": "author",
    "id": 1,
    "name": "Davey Shafik",
    "twitter": "@dshafik",
    "gravatar": "fee39f0c0ffb29d9ac21607ed188be6b"
    }
    },
    {
    "type": "comment",
    "id": "4",
    "content": "fourth",
    "author": {
    "type": "author",
    "id": 2,
    "name": "Jill Random",
    "gravatar": "706b16b2fb732ab6079a10fea61d078b"
    }
    }
    ]
    }

    View Slide

  35. {
    "type": "post",
    "id": "1",
    "title": "JSON API paints my bikeshed!",
    "tags": ["json", "api", "relationships"],
    "author": {
    "type": "author",
    "id": 1,
    "name": "Davey Shafik",
    "twitter": "@dshafik",
    "gravatar": "fee39f0c0ffb29d9ac21607ed188be6b"
    },
    "comments": [
    {
    "type": "comment",
    "id": "1",

    View Slide

  36. {
    "type": "post",
    "id": "1",
    "title": "JSON API paints my bikeshed!",
    "tags": ["json", "api", "relationships"],
    "author": {
    "type": "author",
    "id": 1,
    "name": "Davey Shafik",
    "twitter": "@dshafik",
    "gravatar": "fee39f0c0ffb29d9ac21607ed188be6b"
    },
    "comments": [
    {
    "type": "comment",
    "id": "1",

    View Slide

  37. "gravatar": "fee39f0c0ffb29d9ac21607ed188be6b"
    },
    "comments": [
    {
    "type": "comment",
    "id": "1",
    "content": "FIRST!",
    "author": {
    "type": "author",
    "id": 2,
    "name": "Jill Random",
    "gravatar": "706b16b2fb732ab6079a10fea61d078b"
    }
    },
    {
    "type": "comment",
    "id": "2",

    View Slide

  38. }
    },
    {
    "type": "comment",
    "id": "3",
    "content": "third",
    "author": {
    "type": "author",
    "id": 1,
    "name": "Davey Shafik",
    "twitter": "@dshafik",
    "gravatar": "fee39f0c0ffb29d9ac21607ed188be6b"
    }
    },
    {
    "type": "comment",
    "id": "4",

    View Slide

  39. }
    },
    {
    "type": "comment",
    "id": "3",
    "content": "third",
    "author": {
    "type": "author",
    "id": 1,
    "name": "Davey Shafik",
    "twitter": "@dshafik",
    "gravatar": "fee39f0c0ffb29d9ac21607ed188be6b"
    }
    },
    {
    "type": "comment",
    "id": "4",

    View Slide

  40. }
    },
    {
    "type": "comment",
    "id": "4",
    "content": "fourth",
    "author": {
    "type": "author",
    "id": 2,
    "name": "Jill Random",
    "gravatar": "706b16b2fb732ab6079a10fea61d078b"
    }
    }
    ]
    }

    View Slide

  41. S E R V E R P US H
    CC-BY: Steven Depolo

    View Slide

  42. Ȑ

    View Slide

  43. Ȑ

    View Slide

  44. Ȑ
    GET /post/1

    View Slide

  45. Ȑ
    GET /post/1
    200 OK application/json

    View Slide

  46. GET /post/1/comments
    Ȑ
    GET /post/1
    200 OK application/json

    View Slide

  47. GET /post/1/comments
    GET /post/1/comment/1
    Ȑ
    GET /post/1
    200 OK application/json

    View Slide

  48. Ȑ
    GET /post/1/comments
    GET /post/1/comment/1

    View Slide

  49. Ȑ
    GET /post/1/comment/2
    GET /post/1/comment/3
    GET /post/1/comment/4
    GET /post/1/comments
    GET /post/1/comment/1

    View Slide

  50. Ȑ
    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

    View Slide

  51. Ȑ
    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

    View Slide

  52. D E P E N D E N C I E S
    CC-BY-SA 2.0: David Gamez

    View Slide

  53. A P I R E Q U E ST
    Ɇ
    ɂ
    Ȑ

    View Slide

  54. A P I R E Q U E ST
    Ɇ
    ɂ
    Ȑ

    View Slide

  55. A P I R E Q U E ST
    GET /post/1
    Ɇ
    ɂ
    Ȑ

    View Slide

  56. A P I R E Q U E ST
    GET /post/1
    200 OK application/json
    Ɇ
    ɂ
    Ȑ

    View Slide

  57. S U B - R E S O U R C E P US H W I T H D E P E N D E N C I E S
    Ɇ Ȑ
    GET /post/1
    200 OK application/json

    View Slide

  58. S U B - R E S O U R C E P US H W I T H D E P E N D E N C I E S
    Ɇ Ȑ
    GET /post/1
    200 OK application/json
    /post/1/comments
    /author/1

    View Slide

  59. S U B - R E S O U R C E P US H W I T H D E P E N D E N C I E S
    Ɇ Ȑ
    GET /post/1
    200 OK application/json
    /post/1/comments
    /author/1
    /comment/1
    /comment/…

    View Slide

  60. S U B - R E S O U R C E P US H W I T H D E P E N D E N C I E S
    Ɇ Ȑ
    GET /post/1
    200 OK application/json
    /post/1/comments
    /author/1
    /comment/1
    /images/author/1
    /comment/…

    View Slide

  61. S U B - R E S O U R C E P US H W I T H D E P E N D E N C I E S
    Ɇ Ȑ
    GET /post/1
    200 OK application/json
    /post/1/comments
    /author/1
    /comment/1 /author/2
    /images/author/1
    /comment/…

    View Slide

  62. S U B - R E S O U R C E P US H W I T H D E P E N D E N C I E S
    Ɇ Ȑ
    GET /post/1
    200 OK application/json
    /post/1/comments
    /author/1
    /comment/1 /author/2
    /images/author/1
    /comment/… /author/…

    View Slide

  63. CO D E

    View Slide

  64. $numRequests = 378;

    View Slide

  65. View Slide

  66. $url = 'https://http2.akamai.com/demo/tile-%d.png';
    for ($i = 0; $i <= $numRequests; $i++) {
    $ch = curl_init();

    $opts[CURLOPT_URL] = sprintf($url, $i);
    curl_setopt_array($ch, $opts);
    curl_exec($ch);
    curl_close($ch);
    }
    H T T P/ 1 . 1 : SY N C H R O N O US

    View Slide

  67. $url = 'https://http2.akamai.com/demo/tile-%d.png';
    for ($i = 0; $i <= $numRequests; $i++) {
    $ch = curl_init();

    $opts[CURLOPT_URL] = sprintf($url, $i);
    curl_setopt_array($ch, $opts);
    curl_exec($ch);
    curl_close($ch);
    }
    H T T P/ 1 . 1 : SY N C H R O N O US

    View Slide

  68. $url = 'https://http2.akamai.com/demo/tile-%d.png';
    for ($i = 0; $i <= $numRequests; $i++) {
    $ch = curl_init();

    $opts[CURLOPT_URL] = sprintf($url, $i);
    curl_setopt_array($ch, $opts);
    curl_exec($ch);
    curl_close($ch);
    }
    H T T P/ 1 . 1 : SY N C H R O N O US

    View Slide

  69. $url = 'https://http2.akamai.com/demo/tile-%d.png';
    for ($i = 0; $i <= $numRequests; $i++) {
    $ch = curl_init();

    $opts[CURLOPT_URL] = sprintf($url, $i);
    curl_setopt_array($ch, $opts);
    curl_exec($ch);
    curl_close($ch);
    }
    H T T P/ 1 . 1 : SY N C H R O N O US

    View Slide

  70. $url = 'https://http2.akamai.com/demo/tile-%d.png';
    for ($i = 0; $i <= $numRequests; $i++) {
    $ch = curl_init();

    $opts[CURLOPT_URL] = sprintf($url, $i);
    curl_setopt_array($ch, $opts);
    curl_exec($ch);
    curl_close($ch);
    }
    H T T P/ 1 . 1 : SY N C H R O N O US

    View Slide

  71. $url = 'https://http2.akamai.com/demo/tile-%d.png';
    for ($i = 0; $i <= $numRequests; $i++) {
    $ch = curl_init();

    $opts[CURLOPT_URL] = sprintf($url, $i);
    curl_setopt_array($ch, $opts);
    curl_exec($ch);
    curl_close($ch);
    }
    H T T P/ 1 . 1 : SY N C H R O N O US

    View Slide

  72. 4 7 . 6 7 

    s e co n d s
    CC-BY: Hernán Piñera

    View Slide

  73. $url = 'https://http2.akamai.com/demo/tile-%d.png';
    for ($i = 0; $i <= $numRequests; $i++) {
    $ch = curl_init();

    $opts[CURLOPT_URL] = sprintf($url, $i);

    curl_setopt_array($ch, $opts);
    curl_exec($ch);
    curl_close($ch);
    }
    H T T P/ 2 : SY N C H R O N O US

    View Slide

  74. $url = 'https://http2.akamai.com/demo/tile-%d.png';
    for ($i = 0; $i <= $numRequests; $i++) {
    $ch = curl_init();

    $opts[CURLOPT_URL] = sprintf($url, $i);

    curl_setopt_array($ch, $opts);
    curl_exec($ch);
    curl_close($ch);
    }
    $opts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2;
    H T T P/ 2 : SY N C H R O N O US

    View Slide

  75. $url = 'https://http2.akamai.com/demo/tile-%d.png';
    for ($i = 0; $i <= $numRequests; $i++) {
    $ch = curl_init();

    $opts[CURLOPT_URL] = sprintf($url, $i);

    curl_setopt_array($ch, $opts);
    curl_exec($ch);
    curl_close($ch);
    }
    H T T P/ 2 : SY N C H R O N O US

    View Slide

  76. $url = 'https://http2.akamai.com/demo/tile-%d.png';
    for ($i = 0; $i <= $numRequests; $i++) {
    $ch = curl_init();

    $opts[CURLOPT_URL] = sprintf($url, $i);

    curl_setopt_array($ch, $opts);
    curl_exec($ch);
    curl_close($ch);
    }
    $opts[CURLOPT_HTTP_VERSION] = HTTP_VERSION_2_0;
    H T T P/ 2 : SY N C H R O N O US

    View Slide

  77. $url = 'https://http2.akamai.com/demo/tile-%d.png';
    for ($i = 0; $i <= $numRequests; $i++) {
    $ch = curl_init();

    $opts[CURLOPT_URL] = sprintf($url, $i);

    curl_setopt_array($ch, $opts);
    curl_exec($ch);
    curl_close($ch);
    }
    H T T P/ 2 : SY N C H R O N O US

    View Slide

  78. $url = 'https://http2.akamai.com/demo/tile-%d.png';
    for ($i = 0; $i <= $numRequests; $i++) {
    $ch = curl_init();

    $opts[CURLOPT_URL] = sprintf($url, $i);

    curl_setopt_array($ch, $opts);
    curl_exec($ch);
    curl_close($ch);
    }
    $opts[CURLOPT_HTTP_VERSION] = HTTP_VERSION_2_0;
    H T T P/ 2 : SY N C H R O N O US

    View Slide

  79. 6 2 . 1 9 

    s e co n d s
    CC-BY-NC: Scott Beckner

    View Slide

  80. $mh = curl_multi_init();

    $url = 'https://http2.akamai.com/demo/tile-%d.png';

    for ($i = 0; $i <= $numRequests; $i++) {
    $handles[] = $ch = curl_init();
    $opts[CURLOPT_URL] = sprintf($url, '%d');

    curl_setopt_array($ch, $opts);
    curl_multi_add_handle($mh, $ch);
    }
    H T T P/ 1 . 1 : CO N CU R R E N T

    View Slide

  81. $mh = curl_multi_init();

    $url = 'https://http2.akamai.com/demo/tile-%d.png';

    for ($i = 0; $i <= $numRequests; $i++) {
    $handles[] = $ch = curl_init();
    $opts[CURLOPT_URL] = sprintf($url, '%d');

    curl_setopt_array($ch, $opts);
    curl_multi_add_handle($mh, $ch);
    }
    H T T P/ 1 . 1 : CO N CU R R E N T

    View Slide

  82. $mh = curl_multi_init();

    $url = 'https://http2.akamai.com/demo/tile-%d.png';

    for ($i = 0; $i <= $numRequests; $i++) {
    $handles[] = $ch = curl_init();
    $opts[CURLOPT_URL] = sprintf($url, '%d');

    curl_setopt_array($ch, $opts);
    curl_multi_add_handle($mh, $ch);
    }
    H T T P/ 1 . 1 : CO N CU R R E N T

    View Slide

  83. $mh = curl_multi_init();

    $url = 'https://http2.akamai.com/demo/tile-%d.png';

    for ($i = 0; $i <= $numRequests; $i++) {
    $handles[] = $ch = curl_init();
    $opts[CURLOPT_URL] = sprintf($url, '%d');

    curl_setopt_array($ch, $opts);
    curl_multi_add_handle($mh, $ch);
    }
    H T T P/ 1 . 1 : CO N CU R R E N T

    View Slide

  84. 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);
    }
    }

    View Slide

  85. 8 . 6 6 

    s e co n d s

    View Slide

  86. $url = 'https://http2.akamai.com/demo/tile-%d.png';

    for ($i = 0; $i <= $numRequests; $i++) {
    $handles[] = $ch = curl_init();
    $opts[CURLOPT_URL] = sprintf($url, '%d');
    curl_setopt_array($ch, $opts);
    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();

    View Slide

  87. $url = 'https://http2.akamai.com/demo/tile-%d.png';

    for ($i = 0; $i <= $numRequests; $i++) {
    $handles[] = $ch = curl_init();
    $opts[CURLOPT_URL] = sprintf($url, '%d');
    curl_setopt_array($ch, $opts);
    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();
    $opts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2;

    View Slide

  88. $opts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2;
    $url = 'https://http2.akamai.com/demo/tile-%d.png';

    for ($i = 0; $i <= $numRequests; $i++) {
    $handles[] = $ch = curl_init();
    $opts[CURLOPT_URL] = sprintf($url, '%d');
    curl_setopt_array($ch, $opts);
    curl_multi_add_handle($mh, $ch);
    }
    $mh = curl_multi_init();
    curl_multi_setopt(

    $mh, 

    CURLMOPT_PIPELINING, 

    CURLPIPE_MULTIPLEX

    );

    View Slide

  89. $opts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2;
    $url = 'https://http2.akamai.com/demo/tile-%d.png';

    for ($i = 0; $i <= $numRequests; $i++) {
    $handles[] = $ch = curl_init();
    $opts[CURLOPT_URL] = sprintf($url, '%d');
    curl_setopt_array($ch, $opts);
    curl_multi_add_handle($mh, $ch);
    }
    $mh = curl_multi_init();
    curl_multi_setopt(

    $mh, 

    CURLMOPT_PIPELINING, 

    CURLPIPE_MULTIPLEX

    );

    View Slide

  90. 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);
    }
    }

    View Slide

  91. 2 . 1 4 

    s e co n d s
    CC-BY: motoracereports

    View Slide

  92. H A N D L I N G S E R V E R P US H

    View Slide

  93. $transfers = 1;
    $cb = function(
    $parent, $pushed, $headers
    ) use (&$transfers) {
    $transfers++; // increment to keep track of
    return CURL_PUSH_OK;
    };
    $mh = curl_multi_init();
    curl_multi_setopt($mh, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
    curl_multi_setopt($mh, CURLMOPT_PUSHFUNCTION, $cb);
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "https://localhost:8080/index.html");
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_multi_add_handle($mh, $ch);
    $active = null;
    do {
    $status = curl_multi_exec($mh, $active);

    View Slide

  94. $transfers = 1;
    $cb = function(
    $parent, $pushed, $headers
    ) use (&$transfers) {
    $transfers++; // increment to keep track of
    return CURL_PUSH_OK;
    };
    $mh = curl_multi_init();

    View Slide

  95. $transfers = 1;
    $cb = function(
    $parent, $pushed, $headers
    ) use (&$transfers) {
    $transfers++; // increment to keep track of
    return CURL_PUSH_OK;
    };
    $mh = curl_multi_init();

    View Slide

  96. $transfers = 1;
    $cb = function(
    $parent, $pushed, $headers
    ) use (&$transfers) {
    $transfers++; // increment to keep track of
    return CURL_PUSH_OK;
    };
    $mh = curl_multi_init();

    View Slide

  97. $transfers = 1;
    $cb = function(
    $parent, $pushed, $headers
    ) use (&$transfers) {
    $transfers++; // increment to keep track of
    return CURL_PUSH_OK;
    };
    $mh = curl_multi_init();

    View Slide

  98. $transfers = 1;
    $cb = function(
    $parent, $pushed, $headers
    ) use (&$transfers) {
    $transfers++; // increment to keep track of
    return CURL_PUSH_OK;
    };
    $mh = curl_multi_init();

    View Slide

  99. $transfers = 1;
    $cb = function(
    $parent, $pushed, $headers
    ) use (&$transfers) {
    $transfers++; // increment to keep track of
    return CURL_PUSH_OK;
    };
    $mh = curl_multi_init();

    View Slide

  100. $transfers = 1;
    $cb = function(
    $parent, $pushed, $headers
    ) use (&$transfers) {
    $transfers++; // increment to keep track of
    return CURL_PUSH_OK;
    };
    $mh = curl_multi_init();

    View Slide

  101. $mh = curl_multi_init();
    curl_multi_setopt($mh, 

    CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX

    );
    curl_multi_setopt($mh, 

    CURLMOPT_PUSHFUNCTION, $cb

    );
    $ch = curl_init();
    curl_setopt($ch, 

    CURLOPT_URL, "https://localhost/"

    );

    View Slide

  102. $mh = curl_multi_init();
    curl_multi_setopt($mh, 

    CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX

    );
    curl_multi_setopt($mh, 

    CURLMOPT_PUSHFUNCTION, $cb

    );
    $ch = curl_init();
    curl_setopt($ch, 

    CURLOPT_URL, "https://localhost/"

    );

    View Slide

  103. $mh = curl_multi_init();
    curl_multi_setopt($mh, 

    CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX

    );
    curl_multi_setopt($mh, 

    CURLMOPT_PUSHFUNCTION, $cb

    );
    $ch = curl_init();
    curl_setopt($ch, 

    CURLOPT_URL, "https://localhost/"

    );

    View Slide

  104. $mh = curl_multi_init();
    curl_multi_setopt($mh, 

    CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX

    );
    curl_multi_setopt($mh, 

    CURLMOPT_PUSHFUNCTION, $cb

    );
    $ch = curl_init();
    curl_setopt($ch, 

    CURLOPT_URL, "https://localhost/"

    );

    View Slide

  105. $mh = curl_multi_init();
    curl_multi_setopt($mh, 

    CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX

    );
    curl_multi_setopt($mh, 

    CURLMOPT_PUSHFUNCTION, $cb

    );
    $ch = curl_init();
    curl_setopt($ch, 

    CURLOPT_URL, "https://localhost/"

    );

    View Slide

  106. curl_setopt($ch, 

    CURLOPT_URL, "https://localhost/"

    );
    curl_setopt($ch, 

    CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2

    );
    curl_setopt($ch, 

    CURLOPT_RETURNTRANSFER, 1

    );
    curl_multi_add_handle($mh, $ch);
    $active = null;
    do {

    View Slide

  107. curl_setopt($ch, 

    CURLOPT_URL, "https://localhost/"

    );
    curl_setopt($ch, 

    CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2

    );
    curl_setopt($ch, 

    CURLOPT_RETURNTRANSFER, 1

    );
    curl_multi_add_handle($mh, $ch);
    $active = null;
    do {

    View Slide

  108. curl_setopt($ch, 

    CURLOPT_URL, "https://localhost/"

    );
    curl_setopt($ch, 

    CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2

    );
    curl_setopt($ch, 

    CURLOPT_RETURNTRANSFER, 1

    );
    curl_multi_add_handle($mh, $ch);
    $active = null;
    do {

    View Slide

  109. do {
    $status = curl_multi_exec($mh, $active);
    do {
    $info = curl_multi_info_read($mh);
    if (false !== $info && 

    $info['msg'] == CURLMSG_DONE)
    {
    $handle = $info['handle'];
    if ($handle !== null) {
    $transfers--; // remaining requests
    $out = curl_multi_getcontent(

    $info['handle']

    ); // Response body

    View Slide

  110. do {
    $status = curl_multi_exec($mh, $active);
    do {
    $info = curl_multi_info_read($mh);
    if (false !== $info && 

    $info['msg'] == CURLMSG_DONE)
    {
    $handle = $info['handle'];
    if ($handle !== null) {
    $transfers--; // remaining requests
    $out = curl_multi_getcontent(

    $info['handle']

    ); // Response body

    View Slide

  111. do {
    $status = curl_multi_exec($mh, $active);
    do {
    $info = curl_multi_info_read($mh);
    if (false !== $info && 

    $info['msg'] == CURLMSG_DONE)
    {
    $handle = $info['handle'];
    if ($handle !== null) {
    $transfers--; // remaining requests
    $out = curl_multi_getcontent(

    $info['handle']

    ); // Response body

    View Slide

  112. do {
    $status = curl_multi_exec($mh, $active);
    do {
    $info = curl_multi_info_read($mh);
    if (false !== $info && 

    $info['msg'] == CURLMSG_DONE)
    {
    $handle = $info['handle'];
    if ($handle !== null) {
    $transfers--; // remaining requests
    $out = curl_multi_getcontent(

    $info['handle']

    ); // Response body

    View Slide

  113. do {
    $status = curl_multi_exec($mh, $active);
    do {
    $info = curl_multi_info_read($mh);
    if (false !== $info && 

    $info['msg'] == CURLMSG_DONE)
    {
    $handle = $info['handle'];
    if ($handle !== null) {
    $transfers--; // remaining requests
    $out = curl_multi_getcontent(

    $info['handle']

    ); // Response body

    View Slide

  114. do {
    $status = curl_multi_exec($mh, $active);
    do {
    $info = curl_multi_info_read($mh);
    if (false !== $info && 

    $info['msg'] == CURLMSG_DONE)
    {
    $handle = $info['handle'];
    if ($handle !== null) {
    $transfers--; // remaining requests
    $out = curl_multi_getcontent(

    $info['handle']

    ); // Response body

    View Slide

  115. $handle = $info['handle'];
    if ($handle !== null) {
    $transfers--; // remaining requests
    $out = curl_multi_getcontent(

    $info['handle']

    ); // Response body
    curl_multi_remove_handle($mh, $handle);
    curl_close($handle);
    }
    }
    } while ($info);
    } while ($transfers);
    curl_multi_close($mh);

    View Slide

  116. $handle = $info['handle'];
    if ($handle !== null) {
    $transfers--; // remaining requests
    $out = curl_multi_getcontent(

    $info['handle']

    ); // Response body
    curl_multi_remove_handle($mh, $handle);
    curl_close($handle);
    }
    }
    } while ($info);
    } while ($transfers);
    curl_multi_close($mh);

    View Slide

  117. $handle = $info['handle'];
    if ($handle !== null) {
    $transfers--; // remaining requests
    $out = curl_multi_getcontent(

    $info['handle']

    ); // Response body
    curl_multi_remove_handle($mh, $handle);
    curl_close($handle);
    }
    }
    } while ($info);
    } while ($transfers);
    curl_multi_close($mh);

    View Slide

  118. $handle = $info['handle'];
    if ($handle !== null) {
    $transfers--; // remaining requests
    $out = curl_multi_getcontent(

    $info['handle']

    ); // Response body
    curl_multi_remove_handle($mh, $handle);
    curl_close($handle);
    }
    }
    } while ($info);
    } while ($transfers);
    curl_multi_close($mh);

    View Slide

  119. B LO G A P I + S E R V E R P U S H

    View Slide

  120. class H2PushCache {
    static $cache = [];
    static $pushHandles = [];
    static function addPushHandle($headers, $handle)
    {
    foreach ($headers as $header) {
    if (strpos($header, ':path:') === 0) {
    $path = substr($header, 6);
    $url = curl_getinfo($handle)['url'];
    $url = str_replace(
    parse_url($url, PHP_URL_PATH),
    $path,
    $url
    );
    self::$pushHandles[$url] = $handle;
    }
    }
    }
    static function add($handle)
    {

    View Slide

  121. class H2PushCache {
    static $cache = [];
    static $pushHandles = [];
    static function addPushHandle($headers, $handle)
    {
    foreach ($headers as $header) {
    if (strpos($header, ':path:') === 0) {
    $path = substr($header, 6);
    $url = curl_getinfo($handle)['url'];
    $url = str_replace(
    parse_url($url, PHP_URL_PATH),
    $path,

    View Slide

  122. class H2PushCache {
    static $cache = [];
    static $pushHandles = [];
    static function addPushHandle($headers, $handle)
    {
    foreach ($headers as $header) {
    if (strpos($header, ':path:') === 0) {
    $path = substr($header, 6);
    $url = curl_getinfo($handle)['url'];
    $url = str_replace(
    parse_url($url, PHP_URL_PATH),
    $path,

    View Slide

  123. class H2PushCache {
    static $cache = [];
    static $pushHandles = [];
    static function addPushHandle($headers, $handle)
    {
    foreach ($headers as $header) {
    if (strpos($header, ':path:') === 0) {
    $path = substr($header, 6);
    $url = curl_getinfo($handle)['url'];
    $url = str_replace(
    parse_url($url, PHP_URL_PATH),
    $path,

    View Slide

  124. class H2PushCache {
    static $cache = [];
    static $pushHandles = [];
    static function addPushHandle($headers, $handle)
    {
    foreach ($headers as $header) {
    if (strpos($header, ':path:') === 0) {
    $path = substr($header, 6);
    $url = curl_getinfo($handle)['url'];
    $url = str_replace(
    parse_url($url, PHP_URL_PATH),
    $path,

    View Slide

  125. static function addPushHandle($headers, $handle)
    {
    foreach ($headers as $header) {
    if (strpos($header, ':path:') === 0) {
    $path = substr($header, 6);
    $url = curl_getinfo($handle)['url'];
    $url = str_replace(
    parse_url($url, PHP_URL_PATH),
    $path,
    $url
    );
    self::$pushHandles[$url] = $handle;
    }
    }

    View Slide

  126. static function addPushHandle($headers, $handle)
    {
    foreach ($headers as $header) {
    if (strpos($header, ':path:') === 0) {
    $path = substr($header, 6);
    $url = curl_getinfo($handle)['url'];
    $url = str_replace(
    parse_url($url, PHP_URL_PATH),
    $path,
    $url
    );
    self::$pushHandles[$url] = $handle;
    }
    }

    View Slide

  127. static function add($handle)
    {
    $found = false;
    foreach (self::$pushHandles as $url => $h) {
    if ($handle == $h) {
    $found = $url;
    }
    }
    if (!$found) {
    $found = curl_getinfo($handle)['url'];
    }

    View Slide

  128. static function add($handle)
    {
    $found = false;
    foreach (self::$pushHandles as $url => $h) {
    if ($handle == $h) {
    $found = $url;
    }
    }
    if (!$found) {
    $found = curl_getinfo($handle)['url'];
    }

    View Slide

  129. static function add($handle)
    {
    $found = false;
    foreach (self::$pushHandles as $url => $h) {
    if ($handle == $h) {
    $found = $url;
    }
    }
    if (!$found) {
    $found = curl_getinfo($handle)['url'];
    }

    View Slide

  130. self::$cache[$found] = 

    curl_multi_getcontent($handle);
    }
    static function exists($url)
    {
    if (isset(self::$cache[$url])) {
    return true;
    }
    return false;
    }

    View Slide

  131. self::$cache[$found] = 

    curl_multi_getcontent($handle);
    }
    static function exists($url)
    {
    if (isset(self::$cache[$url])) {
    return true;
    }
    return false;
    }

    View Slide

  132. {
    if (isset(self::$cache[$url])) {
    return true;
    }
    return false;
    }
    static function get($url)
    {
    return self::$cache[$url];
    }
    }

    View Slide

  133. function get_request($url)
    {
    if (H2PushCache::exists($url)) {
    return H2PushCache::get($url);
    }
    $transfers = 1;
    $cb = function ($parent, $pushed, $headers) use (&$transfers) {
    $transfers++; // increment to keep track of the number of concurrent requests
    H2PushCache::addPushHandle($headers, $pushed);
    return CURL_PUSH_OK;
    };
    $mh = curl_multi_init();
    curl_multi_setopt($mh,
    CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX
    );
    curl_multi_setopt($mh,
    CURLMOPT_PUSHFUNCTION, $cb
    );
    $ch = curl_init();
    curl_setopt($ch,
    CURLOPT_URL, $url
    );
    curl_setopt($ch,
    CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2
    );
    curl_setopt($ch,
    CURLOPT_RETURNTRANSFER, 1

    View Slide

  134. function get_request($url)
    {
    if (H2PushCache::exists($url)) {
    return H2PushCache::get($url);
    }
    $transfers = 1;
    $cb = function ($parent, $pushed, $headers)
    use (&$transfers) {
    $transfers++; // increment to keep track of
    the number of concurrent requests
    H2PushCache::addPushHandle($headers,

    View Slide

  135. function get_request($url)
    {
    if (H2PushCache::exists($url)) {
    return H2PushCache::get($url);
    }
    $transfers = 1;
    $cb = function ($parent, $pushed, $headers)
    use (&$transfers) {
    $transfers++; // increment to keep track of
    the number of concurrent requests
    H2PushCache::addPushHandle($headers,

    View Slide

  136. function get_request($url)
    {
    if (H2PushCache::exists($url)) {
    return H2PushCache::get($url);
    }
    $transfers = 1;
    $cb = function ($parent, $pushed, $headers)
    use (&$transfers) {
    $transfers++; // increment to keep track of
    the number of concurrent requests
    H2PushCache::addPushHandle($headers,

    View Slide

  137. function get_request($url)
    {
    if (H2PushCache::exists($url)) {
    return H2PushCache::get($url);
    }
    $transfers = 1;
    $cb = function ($parent, $pushed, $headers)
    use (&$transfers) {
    $transfers++; // increment to keep track of
    the number of concurrent requests
    H2PushCache::addPushHandle($headers,

    View Slide

  138. $transfers = 1;
    $cb = function ($parent, $pushed, $headers)
    use (&$transfers) {
    $transfers++;
    H2PushCache::addPushHandle($headers, $pushed);
    return CURL_PUSH_OK;
    };
    $mh = curl_multi_init();
    curl_multi_setopt($mh,
    CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX

    View Slide

  139. $transfers = 1;
    $cb = function ($parent, $pushed, $headers)
    use (&$transfers) {
    $transfers++;
    H2PushCache::addPushHandle($headers, $pushed);
    return CURL_PUSH_OK;
    };
    $mh = curl_multi_init();
    curl_multi_setopt($mh,
    CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX

    View Slide

  140. do {
    $status = curl_multi_exec($mh, $active);
    do {
    $info = curl_multi_info_read($mh);
    if (false !== $info
    && $info['msg'] == CURLMSG_DONE)
    {
    $handle = $info['handle'];
    if ($handle !== null) {
    $transfers--; // decrement remaining
    H2PushCache::add($handle);
    curl_multi_remove_handle($mh,

    View Slide

  141. do {
    $status = curl_multi_exec($mh, $active);
    do {
    $info = curl_multi_info_read($mh);
    if (false !== $info
    && $info['msg'] == CURLMSG_DONE)
    {
    $handle = $info['handle'];
    if ($handle !== null) {
    $transfers--; // decrement remaining
    H2PushCache::add($handle);
    curl_multi_remove_handle($mh,

    View Slide

  142. $transfers--; // decrement remaining
    H2PushCache::add($handle);
    curl_multi_remove_handle($mh,
    $handle);
    curl_close($handle);
    }
    }
    } while ($info);
    } while ($transfers);
    curl_multi_close($mh);
    return H2PushCache::get($url);
    }

    View Slide

  143. $transfers--; // decrement remaining
    H2PushCache::add($handle);
    curl_multi_remove_handle($mh,
    $handle);
    curl_close($handle);
    }
    }
    } while ($info);
    } while ($transfers);
    curl_multi_close($mh);
    return H2PushCache::get($url);
    }

    View Slide

  144. $url = 'https://example/post/1';
    $response = get_request($url);
    $post = json_decode($response);
    $response = get_request($post->comments);
    $comments = json_decode($reponse);
    $response = get_request($post->author);
    $author = json_decode($response);

    View Slide

  145. $url = 'https://example/post/1';
    $response = get_request($url);
    $post = json_decode($response);
    $response = get_request($post->comments);
    $comments = json_decode($reponse);
    $response = get_request($post->author);
    $author = json_decode($response);

    View Slide

  146. $url = 'https://example/post/1';
    $response = get_request($url);
    $post = json_decode($response);
    $response = get_request($post->comments);
    $comments = json_decode($reponse);
    $response = get_request($post->author);
    $author = json_decode($response);

    View Slide

  147. $url = 'https://example/post/1';
    $response = get_request($url);
    $post = json_decode($response);
    $response = get_request($post->comments);
    $comments = json_decode($reponse);
    $response = get_request($post->author);
    $author = json_decode($response);

    View Slide

  148. $url = 'https://example/post/1';
    $response = get_request($url);
    $post = json_decode($response);
    $response = get_request($post->comments);
    $comments = json_decode($reponse);
    $response = get_request($post->author);
    $author = json_decode($response);

    View Slide

  149. $url = 'https://example/post/1';
    $response = get_request($url);
    $post = json_decode($response);
    $response = get_request($post->comments);
    $comments = json_decode($reponse);
    $response = get_request($post->author);
    $author = json_decode($response);

    View Slide

  150. T H A N K S !

    View Slide