This is an old revision of the document!
PHP RFC: ext/curl HTTP/2 Server Push Support
- Version: 0.1
- Date: 2015-10-01
- Author: Davey Shafik, davey@php.net
- Status: Under Discussion
- First Published at: https://wiki.php.net/rfc/curl_http2_push
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, but broken till the as-yet-unreleased 7.46.0 (See: this and this github issues for details).
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 $transfers = 1; $callback = function($parent_ch, $pushed_ch, array $headers) use (&$transfers) { $transfers++; // increment to keep track of the number of concurrent requests return CURL_PUSH_OK; }; $mh = curl_multi_init(); curl_multi_setopt($mh, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); curl_multi_setopt($mh, CURLMOPT_PUSHFUNCTION, $callback); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://localhost:8080/index.html"); curl_setopt($ch, CURLOPT_HTTP_VERSION, 3); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Debugging/Local stuff //curl_setopt($ch, CURLOPT_VERBOSE, 1); // will output curl debugging information curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // self-signed cert curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // self-signed cert curl_multi_add_handle($mh, $ch); $active = null; 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 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);
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 C callback is registered that will call the callable set in php\curl_multi_setopt()
(and passed to the C callback using curls CURLMOPT_PUSHDATA
).
We do not support CURLMOPT_PUSHDATA
. Instead, the user can use closures and use
with references to replicate this behavior.
libcurl exposes the push headers with two functions functions curl_pushheader_bynum()
and curl_pushheader_byname()
. We can use curl_pushheader_bynum()
to create an array of header lines. These would then be parsed in user land (as with regular request headers).
Backward Incompatible Changes
No breaks
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
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
Some memory leaks
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
Implementation
After the project is implemented, this section should contain
- the version(s) it was merged to
- a link to the git commit(s)
- 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.