rocket-nginx icon indicating copy to clipboard operation
rocket-nginx copied to clipboard

$http_host can be empty when using http3

Open realrellek opened this issue 2 months ago • 3 comments

Describe the bug When using http3, the $http_host variable may be empty. It is used by the config file tho to determine where in the file system the cache file could be. So this fails, thus yielding a cache miss, and going through the php system.

If that happens, it'll result in a cache url like /var/customers/webs/wum/domain.tld/wp-content/cache/wp-rocket/////index-https.html which doesn't exist, thus the miss.

Versions What version of Nginx are you using ? 1.28.0 What version of Rocket-Nginx are you using ? 3.1.1 What version of WP Rocket are you using ? 3.20.1.2 Are you using Nginx as a reverse proxy (with Apache for instance) ? nope

To Reproduce Steps to reproduce the behaviour: I'm not actually sure because even on my server, the $http_host variable is set sometimes, and sometimes not. But it has to do with http3 as per google.

Did you activate the debug in Rocket-Nginx ? Please do and include any headers.

x-rocket-nginx-file: /var/customers/webs/wum/domain.tld/wp-content/cache/wp-rocket/////index-https.html
x-rocket-nginx-reason: File not cached
x-rocket-nginx-serving-static: MISS

/etc/nginx/sites-enabled/35_froxlor_ssl_vhost_domain.tld.conf:

# 35_froxlor_ssl_vhost_domain.tld.conf
# Created 16.11.2025 18:54
# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.

server {
        listen [dead:beef:c0fe:babe::2]:443 ssl;
        http2 on;
        listen [dead:beef:c0fe:babe::2]:443 quic;
        listen 69.69.69.69:443 ssl;
        listen 69.69.69.69:443 quic;
        add_header Alt-Svc 'h3=":443"; ma=86400';
        http3 on;
        http3_hq on;
        quic_gso on;
        quic_retry on;
        server_name domain.tld www.domain.tld domain.othertld www.domain.othertld;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
        ssl_dhparam /etc/ssl/webserver/dhparams.pem;
        ssl_prefer_server_ciphers off;
        ssl_session_tickets on;
        ssl_session_cache shared:SSL:10m;
        ssl_certificate /etc/ssl/froxlor-custom/domain.tld.crt;
        ssl_certificate_key /etc/ssl/froxlor-custom/domain.tld.key;
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
        include /etc/apache2/conf-enabled/acme.conf;
        access_log /var/customers/logs/wum-domain.tld-access.log combined;
        error_log /var/customers/logs/wum-domain.tld-error.log warn;
        root /var/customers/webs/wum/domain.tld/;
        location / {
                index index.php index.html index.htm;
                try_files $uri $uri/ /index.php?$args;
        }

        location ^~ /goaccess {
                alias /var/customers/webs/wum/goaccess/domain.tld/;
                auth_basic "Restricted Area";
                auth_basic_user_file /etc/nginx/froxlor-htpasswd/1-c123456789.htpasswd;
        }

        location ~ ^(.+?\.php)(/.*)?$ {
                include /etc/nginx/fastcgi_params;
                fastcgi_split_path_info ^(.+?\.php)(/.*)$;
                fastcgi_param SCRIPT_FILENAME $request_filename;
                fastcgi_param PATH_INFO $2;
                fastcgi_param HTTPS on;
                fastcgi_pass unix:/var/lib/apache2/fastcgi/1-wum-domain.tld-php-fpm.socket;
                fastcgi_index index.php;
        }

        location ~ /\. {
                deny all;
        }

        charset utf-8;
        etag off;
        gzip on;
        gzip_vary on;
        gzip_types
        application/atom+xml
        application/javascript
        application/json
        application/rss+xml
        application/vnd.ms-fontobject
        application/x-font-ttf
        application/xhtml+xml
        application/xml
        font/opentype
        image/svg+xml
        image/x-icon
        text/css
        text/plain
        text/x-component
        text/xml;
        add_header X-Robots-Tag "noarchive";
        if ($host != "www.domain.tld") {
                return 301 https://www.domain.tld$request_uri;
        }

        if ($args ~* "wptouch_switch=") {
                return 301 $uri; # $uri hat keinen Query String
        }

        rewrite ^/kategorie/(.+)/www\.domain\.othertld/(.+)$ https://www.domain.tld/$2 permanent;
        rewrite (.+)/amp/?$ $1 permanent;
        location = /sitemap-news.xml {
                return 301 https://www.domain.tld/post_google_news.xml;
        }

        location = /sitemap.xml {
                return 301 https://www.domain.tld/sitemapindex.xml;
        }

        include /etc/nginx/snippets/wum-domain-redirects.conf;
        location ~ /\.user\.ini$ {
                deny all;
        }

        include /etc/nginx/rocket-nginx/conf.d/default.conf;
        client_max_body_size 512M;
        client_body_buffer_size 2M;
        location ~* ^(/.+)\.(jpg|jpeg|jpe|png|gif)$ {
                add_header Vary Accept;
                set $canavif 1;
                if ($http_accept !~* "avif") { set $canavif 0;
                }

                if (!-f $request_filename.avif) { set $canavif 0; }
                if ($canavif = 1) {
                        rewrite ^(.*)$ $1.avif break;
                }

                set $canwebp 1;
                if ($http_accept !~* "webp") { set $canwebp 0; }
                if (!-f $request_filename.webp) { set $canwebp 0; }
                if ($canwebp = 1) {
                        rewrite ^(.*)$ $1.webp break;
                }

        }

        location = /fpm-status {
                allow 127.0.0.1;
                allow ::1;
                allow 69.69.69.69; # Deine Monitoring-IP, nehme ich an
                deny all;
                set $fpm_socket "unix:/var/lib/apache2/fastcgi/1-wum-domain.tld-php-fpm.socket";
                if ($fpm_socket = "unix:") {
                        return 404;
                }

                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME "";
                fastcgi_param SCRIPT_NAME /fpm-status;
                fastcgi_pass $fpm_socket;
        }

}

Expected behavior It should use a populated variable

Additional context I also had to add this:

fastcgi_param  HTTP_HOST       $host;
fastcgi_param  HTTP_HOST      $http_host if_not_empty;

into /etc/nginx/fastcgi_params because otherwise PHP scripts are going crazy. It is a somewhat documented thing, tho nginx doesn't seem to feel responsible to "fix" this.

I'd propose that the config file doesn't rely on $http_host but sets its own variable, and checks if $http_host has something useful, and if not, it uses $host.

realrellek avatar Nov 16 '25 19:11 realrellek