How to Send a Http/2 Post Request in PHP

How do I send a HTTP/2 POST request in PHP

The CURL extension for PHP >= 5.5.24 has support for HTTP/2. (since this commit)

You also need a libcurl installed — the underlying library that the curl functions use — with HTTP/2 support enabled. That means a libcurl newer than 7.38.0 but really, the newer the better. Libcurl has to have been built with HTTP/2 support explicitly enabled, using the --with-nghttp2 flag at compile time.

Just use curl as you'd normally use it, and set the CURLOPT_HTTP_VERSION option to use HTTP/2 by passing in CURL_HTTP_VERSION_2_0. Then you'll get the request upgraded to version 2 if the client and server both support it.

Prior to PHP 5.5.24, if libcurl has been built with HTTP/2 support, you can pass in the int value of CURL_HTTP_VERSION_2_0 explicitly as PHP will still pass it through to libcurl. Currently, it has a value of 3 — this should not change, but could.

if (!defined('CURL_HTTP_VERSION_2_0')) {
define('CURL_HTTP_VERSION_2_0', 3);
}

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

Make HTTP/2 request with PHP

As far as I'm aware, cURL is the only transfer method in PHP that supports HTTP 2.0.

You'll first need to test that your version of cURL can support it, and then set the correct version header:

if (
defined("CURL_VERSION_HTTP2") &&
(curl_version()["features"] & CURL_VERSION_HTTP2) !== 0
) {
$url = "https://www.google.com/";
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL =>$url,
CURLOPT_HEADER =>true,
CURLOPT_NOBODY =>true,
CURLOPT_RETURNTRANSFER =>true,
CURLOPT_HTTP_VERSION =>CURL_HTTP_VERSION_2_0,
]);
$response = curl_exec($ch);
if ($response !== false && strpos($response, "HTTP/2") === 0) {
echo "HTTP/2 support!";
} elseif ($response !== false) {
echo "No HTTP/2 support on server.";
} else {
echo curl_error($ch);
}
curl_close($ch);
} else {
echo "No HTTP/2 support on client.";
}

How to send a HTTP/2.0 request with node.js

Get request:

const http2 = require("http2");
const client = http2.connect("https://www.google.com");

const req = client.request({
":path": "/"
});

let data = "";

req.on("response", (headers, flags) => {
for (const name in headers) {
console.log(`${name}: ${headers[name]}`);
}

});

req.on("data", chunk => {
data += chunk;
});
req.on("end", () => {
console.log(data);
client.close();
});
req.end();

POST Request

     let res = "";
let postbody = JSON.stringify({
key: value
});
let baseurl = 'baseurl'
let path = '/any-path'
const client = http2.connect(baseurl);
const req = client.request({
":method": "POST",
":path": path,
"content-type": "application/json",
"content-length": Buffer.byteLength(postbody),
});

req.on("response", (headers, flags) => {
for (const name in headers) {
console.log(`${name}: ${headers[name]}`);
}

});
req.on("data", chunk => {
res = res + chunk;
});
req.on("end", () => {
client.close();
});

req.end(postbody)

For more details pls see this official documents:
https://nodejs.org/api/http2.html#http2_client_side_example

How to make HTTP/2 requests via API

https://www.reddit.com/r/PHP/comments/301ncp/http2_support_for_curl_merged/

This simply means that you can optionally tell curl_*() to communicate with the remote server via HTTP/2.0. If the remote server doesn't support the protocol the two parties will speak HTTP/1.1 as before. There are two scenarios in PHP userland where you can benefit from the use of HTTP/2.0 in a curl client:

  1. You're retrieving multiple resources from the same site concurrently over the same connection; you may experience performance improvement by avoiding the "head-of-line" blocking problem because HTTP/2.0 allows the multiplexing of multiple transfers concurrently over the same TCP connection.
  2. You're connecting via HTTPS (h2). Encrypted h2 sessions are negotiated as part of the TLS handshake via the TLS ALPN extension. This means you can establish the crypto session with fewer TCP roundrips via HTTP/2.0 than you'd be able to do with HTTP/1.1 (a performance benefit).

cURL will handle the work for you, essentially.

How to detect if a site supports HTTP/2 in PHP

Update 2021-02-25:

As mentioned by djdance, HTTP/2.0 has been HTTP/2 for some time now. Therefore, you should really check against HTTP/2 (and HTTP/3 for the upcoming HTTP 3).

If you do not want to use strpos, you can now also use str_starts_with($response, "HTTP/2") when using PHP 8. Otherwise you can use substr($response, 0, 6) === "HTTP/2" for PHP 7.

For PHP 7.3 and cURL 7.50.0, curl_getinfo now also supports CURLINFO_HTTP_VERSION:

echo curl_getinfo($ch, CURLINFO_HTTP_VERSION);
// 3 for HTTP/2

The values which may be returned by CURLINFO_HTTP_VERSION (as of PHP 7.3):

CURL_HTTP_VERSION_NONE              === 0
CURL_HTTP_VERSION_1_0 === 1
CURL_HTTP_VERSION_1_1 === 2
CURL_HTTP_VERSION_2 === 3
CURL_HTTP_VERSION_2_0 === 3
CURL_HTTP_VERSION_2TLS === 4
CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE === 5

This means you can check for a specific (e.g., CURL_HTTP_VERSION_2TLS, which is HTTP/2 over TLS):

if (
$response !== false
&& curl_getinfo($ch, CURLINFO_HTTP_VERSION) === CURL_HTTP_VERSION_2TLS
) {
// The connection was established using HTTP/2 over TLS
// if the server does not support TLS HTTP/1.1 will be used.
}

Original:

Both your server and your installation of cURL need to support HTTP/2.0. After that you can just make a normal cURL request and add the CURLOPT_HTTP_VERSION parameter which will make cURL try to make an HTTP/2.0 request. After that you'll have to check the Headers from the request to check if the server does indeed support HTTP/2.0.

Example:

$url = "https://google.com";
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_HEADER => true,
CURLOPT_NOBODY => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0, // cURL will attempt to make an HTTP/2.0 request (can downgrade to HTTP/1.1)
]);
$response = curl_exec($ch);

Now you'll need to check if cURL did indeed make an HTTP/2.0 request:

if ($response !== false && strpos($response, "HTTP/2.0") === 0) {
echo "Server of the URL has HTTP/2.0 support."; // yay!
} elseif ($response !== false) {
echo "Server of the URL has no HTTP/2.0 support."; // nope!
} else {
echo curl_error($ch); // something else happened causing the request to fail
}
curl_close($ch);


Related Topics



Leave a reply



Submit