====== PHP RFC: ext/curl HTTP/2 Server Push Support ====== * Version: 0.1 * Date: 2015-10-01 * Author: Davey Shafik, davey@php.net * Status: Implemented (PHP 7.1) * 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 [[https://github.com/php/php-src/pull/1497|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: [[https://github.com/bagder/curl/issues/529|this]] and [[https://github.com/bagder/curl/issues/530|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 ===== ===== Implementation ===== Within [[https://github.com/php/php-src/blob/master/ext/curl/multi.c#L409|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 ===== Possibly a memory leak in libcurl ===== Future Scope ===== This change should track libcurl. ===== Vote ===== Simple Yes/No option. Requires 50%+1 to be accepted. This vote will close on 13:00 UTC on Wed 2015-12-23 * Yes * No ===== Patches and Tests ===== - Working patch can be found [[https://github.com/dshafik/php-src/compare/curl-http2-push|here]] - Docker container for easy testing can be found [[http://github.com/dshafik/php-http2-push-example|here]] ===== Implementation ===== Server push support has been implemented in PHP 7.1 with [[http://git.php.net/?p=php-src.git;a=commit;h=ad15e1ccdabc678103e356535919e829ba9a0281|commit ad15e1cc]], and is documented in the [[http://php.net/manual/function.curl-multi-setopt.php|curl_multi_setopt man page]]. The language specification is not affected by this RFC. ===== References ===== - [[https://github.com/bagder/curl/wiki/HTTP-2-Server-Push|libcurl HTTP/2 implementation]] - [[http://daniel.haxx.se/blog/2015/06/03/server-push-to-curl/|libcurl creators blog post about the implementation]] ===== Rejected Features ===== None