7

I've been migrating to a new host (AWS Lightsail with a Ubuntu instance) and while everything is working just fine I'm running into a quirk that I can't quite figure out.

I've enabled HTTP2 on my virtual server and confirmed that files are using that protocol (via DevTools and http2.pro):

HTTP2 working in DevTools

HTTP2 working per http2.pro

For reference, here is my server showing the Apache HTTP2 mod is enabled (and I did restart apache afterwords)

http2 mod already enabled

However, in PHP when I output $_SERVER['SERVER_PROTOCOL'] on my server it is still showing "HTTP/1.1":

http1.1

php code

But this same exact software (WordPress theme) on other servers is showing "HTTP/2.0" correctly:

http2 detected with same exact code

I believe I have my Apache2 conf files setup correctly:

Port 443:

<VirtualHost *:443>
    Protocols h2 h2c http/1.1

and just to be thorough I did Port 80 as well:

<VirtualHost *:80>
    Protocols h2 h2c http/1.1

Unfortunately I do not have access to the conf files (or ssh) on the server that is working, so I can't cross-reference those files.

I've been reading a bunch of tutorials on HTTP2 to see if there is any additional setting or configuration that I may have missed, but most are showing the same instructions that I've implemented.

Can anyone point me in the right direction as to why this PHP "detection" is incorrectly displaying the protocol, or if there is something I missed that is preventing PHP from using HTTP2 in this one situation?

5
  • Did you checked the error.log of your apache? Since Apache 2.4.25 the MPM prefork does not support HTTP2. Are you using MPM? Then you have to switch to FPM.
    – Marius
    Jul 31 '20 at 6:20
  • I read through the Apache error.log file, but only had some warnings and notices for different virtual servers (the one in question does not appear to have any errors). Outputting phpinfo() I can see that the Server API is FPM/FastCGI. Jul 31 '20 at 12:33
  • 1
    Doesn't HTTP2 need to be supported by the client as well? I'm thinking so you might get downgraded if there's a proxy in the middle for instance. Jul 31 '20 at 12:47
  • All of the screenshots were taken from the same browser/client and connection, and neither server is using anything non-standard as far as their setup goes, so no proxy is involved anywhere that I'm aware of. Jul 31 '20 at 12:59
  • 1
    Could be an issue similar to stackoverflow.com/questions/17640877/… .
    – Kannan
    Aug 2 '20 at 16:56
5

This has to do with how Cloudflare connects to servers. Although it does serve the client via HTTP2 (or HTTP3), it still connects to the server itself via HTTP1.1.

Cloudflare only uses HTTP/1.x between the origin web server and Cloudflare.

https://support.cloudflare.com/hc/en-us/articles/200168076-Are-the-HTTP-2-or-SPDY-protocols-supported-between-Cloudflare-and-the-origin-server-#6ncFUWOVRaVtPzYN1euBIC

This particular post helped illuminate the issue for me: https://community.cloudflare.com/t/passing-the-correct-server-protocol-to-the-origin/82386

I wish Cloudflare made it more obvious on their HTTP/2 Network setting that this was the case...

2
  • 2
    So there is a proxy in the middle. Aug 2 '20 at 20:42
  • Correct- that's what it turned out to be. In my mind I was not thinking of Cloudflare as a proxy. I know I submitted this answer myself, but @Marius Cucuruz is entitled to the bounty for correctly identifying the problem (not sure if that is possible...). Aug 3 '20 at 21:08
2

Thank you, the QA here helped me to solve my issue. Here are specifics in case others run into similar issues with PHP "detection" incorrectly displaying the protocol behind a proxy such as Cloudflare.

I found this Cloudflare SSL trick which would solve the issue for every php file executed. However, under a shared hosting environment I do not have access to modify php.ini

My issue cropped up in a Wordpress theme named Blocksy that relied on the PHP variable $_SERVER['HTTPS'] internally to generate a URL for loading its sticky.js component. This caused a mixed content warning blocking the js from operating under Cloudflare SSL. Under Wordpress, all php execution comes after wp-config.php so I added the following php in that file to solve this problem.

/* Cloudflare HTTPS help 
How this works - this will automatically run before WordPress
The following will check if cloudflare has set the HTTPS protocol forwarding header (HTTP_X_FORWARDED_PROTO) and will adjust the $_SERVER variables accordingly if so.
*/
if(!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'){
        $_SERVER['REQUEST_SCHEME'] = str_replace('http', 'https', $_SERVER['REQUEST_SCHEME']);
        $_SERVER['SERVER_PROTOCOL'] = str_replace('HTTP', 'HTTPS', $_SERVER['SERVER_PROTOCOL']);
        $_SERVER['HTTPS'] = 'on';
}
/* END  Cloudflare HTTPS help */
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.