rfc:curl_http2_push

This is an old revision of the document!


PHP RFC: ext/curl HTTP/2 Server Push Support

Introduction

With the introduction of HTTP/2 support in libcurl, PHP 7.0 now has some support for HTTP/2 requests, but it does not yet support one of the (potentially) most powerful features: Server push.

Server push allows the server to push additional resources relevant to the requested resource directly to the client proactively.

Server push is available in libcurl since 7.44.0.

Libcurl Implementation

libcurl supports registering a callback for multi handlers to handle server pushes via the CURLMOPT_PUSHFUNCTION and CURLMOPT_PUSHDATA options for curl_multi_setopt().

The callback will be passed the parent curl handle (the request the client made), a new curl handle for the pushed request, the number of headers, the PUSH_PROMISE headers, and a user-defined pointer (set using CURLMOPT_PUSHDATA).

The callback then returns either CURL_PUSH_OK if can handle the push, or CURL_PUSH_DENY to reject it.

The new curl handle is then added to the multi handler and is then included in the handling of multiple requests.

Suggested Implementation

<?php
$user_data = null;
 
$callable = function ($push_ch, $parent_ch, $header_count, array $headers) use (&$user_data)
{
      if ($header_count > 0 && isset($headers['content-type']) && $headers['content-type'][0] !== 'application/json') {
           return CURL_PUSH_DENY;
      }
      return CURL_PUSH_OK;
}
 
$mh = curl_multi_init();
 
curl_multi_setopt($mh, CURLMOPT_PUSHFUNCTION, $callable);
?>

Implementation

Within the PHP implementation of curl_multi_setopt() (referenced as php\curl_multi_setopt()) there is a switch that handles different options. When CURLMOPT_PUSHFUNCTION is set a callback is registered that will call the callable set in php\curl_multi_setopt().

We do not support CURLMOPT_PUSHDATA. Instead, the user can use closures and use with references to replicate this behavior.

We also have to handle the $headers argument, which I believe will have to be a resource for it to work — this will then be passed into two new libcurl functions curl_pushheader_bynum() and curl_pushheader_byname(). libcurl does not expose the headers through any other mechanism from nghttp2, so we either have to duplicate the internal libcurl code that accesses the nghttp2 header data, or we have to use these accessors. The former seems very brittle to me.

Backward Incompatible Changes

No breaks, except possibly the referenced value for php\curl_multi_setopt().

Proposed PHP Version(s)

PHP 7.1

RFC Impact

To SAPIs

No impact

To Existing Extensions

No impact outside of BC compatible changes to ext/curl

To Opcache

No impact on Opcache

New Constants

  • CURLMOPT_PUSHFUNCTION
  • CURLMOPT_PUSHDATA
  • CURL_PUSH_OK
  • CURL_PUSH_DENY

These are directly exposed from libcurl, and documentation can be taken from there.

php.ini Defaults

None

Open Issues

  1. Adding a new resource isn't desirable but fits the current ext/curl API

Future Scope

This change should track libcurl.

Proposed Voting Choices

Two choices: Add, Deny 50% required as this is not a language change

Patches and Tests

Patch is currently being worked on here

Implementation

After the project is implemented, this section should contain

  1. the version(s) it was merged to
  2. a link to the git commit(s)
  3. a link to the PHP manual entry for the feature

References

Rejected Features

Keep this updated with features that were discussed on the mail lists.

rfc/curl_http2_push.1447652026.txt.gz · Last modified: 2017/09/22 13:28 (external edit)