-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HTTP/2 Support #1249
Comments
👍 |
Thanks for putting this together, @dshafik! Note that the preferred way of specifying the HTTP version is through the use GuzzleHttp\Client;
$client = new Client();
$client->get('https://http2.akamai.com/demo/tile-0.png', [
'versionl' => 2.0,
'debug' => true,
]);
Because we are using callbacks to receive data, this seems like a bug in either PHP or cURL. Setting CURLOPT_RETURNTRANSFER, from what I understand, would unnecessarily buffer the response in memory. |
Can confirm that |
👍 |
4 similar comments
👍 |
👍 |
👍 |
👍 |
@mtdowling check out master...dshafik:http2-tests — I'm really not happy about this, so if you have a better suggestions, that'd be great. Because the current So once I had that I the ability to specify a HTTP version for It will start the HTTP/1.1 server on port 8126, and HTTP/2 on 8127 (with SSL). I then simply extend the original test, and Goals:
Examples: Issues:
|
Just have a few minutes for now to look at this. I'll try to find more time later to provide more feedback. I don't like changing the existing static public properties of the test class to return arrays and use functions. I think it would be better to somehow add new matching properties for HTTP/2 variables (e.g.,
I don't think Guzzle, PHP's HTTP/2 support, or HTTP/2 in general are ready to be the default way that Guzzle sends requests. I think HTTP/2 should be an opt-in at this point. |
Guzzle HTTP/2 comment @mtdowling I agree about not having HTTP/2 as default, but I meant it should fall back to HTTP/1.1 when attempting to use HTTP/2 on a system where Ideally the only difference between the two APIs would be that you set the version to 2, HTTP/1.1 would use pipelining for async, where 2 would use multiplexing. Non-async requests would just use the requested protocol if possible. As I said, I'm not really happy with the test suite, so any more concrete suggestions would be great! |
Nice! 👍 |
Some minor updates:
|
@mtdowling I'd very much like to move this forward, where do you stand on it? |
Hey @dshafik @mtdowling I'm very curious about this myself. HTTP/2 has been around for a while now, and we can't keep ignoring it forever. I'm starting to use it over in Ruby land more and more, but our company has a bunch of PHP and I want them to get in on the party. My experiments are using a ruby implementation https://github.com/ostinelli/net-http2, which is a little different to your curl-based approach. Anyway, necrobump. |
Hello anyone please help me? I have two project separated: (1.) Laravel for user Key-in Data (2.) Laravel for API (1.) Key-in Data Project $client = new Client(['headers' => ['X-Client-Code' => env('KEY_CODE')]]);
$request_param = [
'client_id' => $request->client_id,
'code' => $request->code,
'phone_number' => $request->phone_number,
'sms_type' => 'card'
];
$request_data = json_encode($request_param);
$res = $client->request(
'POST',
url(env('API_URL').'api/v0/user/activation'),
[
'headers' => [
'Accept' => 'application/json',
'Authorization' => file_get_contents(storage_path('credential').'/.token')
],
'body' => $request_data
]
);
return $res->getBody()->getContents(); (2.) Laravel API $ehealth_code = $request->headers->get('x-client-code');
$data = json_decode($request->getContent(),true); // return empty Anyone know why on Ubuntu server |
this issue is from 2015. Can I make PR for this feature? |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 2 weeks if no further activity occurs. Thank you for your contributions. |
Hey folks! I know we're all super busy and I wouldn't normally hassle or bump, but this bot is throwing some shade into a very important issue which has so far been progressing in a rather underwhelming fashion. Is anything going to happen here? Can we be whelmed?! HTTP/3 is on the way so now more than ever it is time to consider moving beyond the restrictions of ye-olde HTTP/1. |
Yeah, it would nice to have this finally in Guzzle! Sadly, I don't think we have any resources for this right now, so any help would be much appreciated (it's going to be Hacktoberfest soon after all). |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 2 weeks if no further activity occurs. Thank you for your contributions. |
I dont follow the specifications discussions too carefully, but isn't H2 push considered as a misstake? Ie, it is cool and all, but it is not as useful and we first thought. |
This issue is intended to document the current and ongoing status of HTTP/2 support in Guzzle.
Current Status
Using Curl
The only handler that can support HTTP/2 at present is Curl (see below for streams handler info).
For Curl to support HTTP/2 needs to be built with
--with-nghttp2
and be>= 7.33.0
. For multiplex support, you need>= 7.43.0
.To detect support for HTTP/2 in libcurl from PHP, you must use:
The
CURL_VERSION_HTTP2
constant was added in PHP 5.5.24, by using the constant value,65536
, or adding something like this to cover all HTTP/2 related constants:At present, with the merge of #1246, it is now possible to use HTTP/2 for synchronous requests:
This will yield debug output including the following, indicating it's using HTTP/2 successfully:
Unfortunately, if you attempt to use it with libcurl compiled without http2 support, then the following happens:
First the response from the request is output to STDOUT (because
CURLOPT_RETURNTRANSFER
is set tofalse
and it seems to fail to use the streams stuff), then the following exception is thrown:Backwards Compatibility
We should transparently downgrade to HTTP/1.1, and
CURLPIPE_HTTP1
, if libcurl does not support HTTP/2, and/or multiplexing respectively.Using Streams
To implement HTTP/2 for the streams adapter would require either:
h2://
orhttp2://
or some such (or both).Testing HTTP/2
To properly test HTTP/2 support, we need to do a few different test approaches:
HTTP/2 Client -> HTTP/2 Server
The current
server.js
only supports HTTP/1.1, which means that we cannot test actual HTTP/2 requests against it. However, there is a fairly drop-in replacement for node'shttp
module, which ishttp2
found here: https://github.com/molnarg/node-http2. I currently have updateGuzzleHttp\Tests\Server
to allow you to specify which version of HTTP being used, and spin upserver.js
or a newserver2.js
— however these scripts are nearly identical and it would be trivial to handle that as an argument sent toserver.js
. The entire diff looks like this:HTTP/2 Client -> HTTP/1.1 Server
Currently libcurl always does an HTTP/1.1 request and attempts to upgrade the connection to HTTP/2, this method is available so that you can always make HTTP/2 requests regardless of server support, and it will automatically fall back to HTTP/1.1. Support for prior-knowledge requests are planned for libcurl, so it might be possible to do native HTTP/2 rather than HTTP/1.1+Upgrade in the future.
This means we should also run HTTP/2 intended requests against the existing HTTP/1.1 server.
It would be great if it were possible to detect failure to upgrade and to switch to
CURLPIPE_HTTP1
transparently if they were attempting to useCURLPIPE_MULTIPLEX
.Desired API
Enabling HTTP/2 should be as simple as setting the request option
version => 2
(or2.0
). Due to the HTTP/2 upgrade negotiation, it's entirely BC to actually set this as the default (see performance related section below).This means that it will automatically use HTTP/1.1 if HTTP/2 is not available, we do not have to handle this ourselves.
Once the
version
is set, concurrent requests should attempt to use HTTP/2 multiplexing. Failing to do so should switch to HTTP pipelining transparently.While the overhead of
CURLPIPE_HTTP1
is greater, it drastically faster than not using it, giving closer to the performance expected withCURLPIPE_MULTIPLEX
.Server Push
Server push is the ability for the HTTP server to inject responses into the clients cache in response to a different request that it expects will also be wanted. An example of this would be requesting an HTML page, and having the server also push you the CSS, JS, and images, rather than waiting for the client to have to parse the HTML and make additional requests for those resources.
libcurl supports this feature in
>= 7.44.0
, and it works by registering a callback to accept or reject the request. The callback accepts (among other things) an easy handle representing the request. Rejecting the request requires returningCURL_PUSH_DENY
, otherwise if you returnCURL_PUSH_OK
it will add the easy handle to the multihandler and you can handle it as you would normally from that point.If the callback is not defined then all server pushes are rejected automatically.
PHP does not currently support this feature.
Also, while this feature is callback based, it might be the most difficult to implement consistently among handlers. I would recommend waiting till at least one other handler supports it before implementing.
HTTP/2 Performance & When To Use It
Currently, sending a single HTTP request using HTTP/2 is slower than using HTTP/1.1. I believe this might be to do with the HTTP/1.1+Upgrade that is done. This means if you are doing just 1:1 request:host then you should use HTTP/1.1 at present.
However you are doing multiple HTTPS requests to the same host, and using multiplexing, then you get a significant performance increase due to only needing a single SSL negotiation for all requests on the same multiplexed connection.
The text was updated successfully, but these errors were encountered: