Score:1

Wordpress NGINX + FastCGI Cache, Err_too_many_requests

es flag

Have a weird situation with my Wordpress set up running NGINX and PHP8.0 with FastCGI Cache.

The site will end up in a too many requests loop, however, it doesn't happen immediately and will come out of this loop by itself.

E.g. it could work fine for 8 hours, and then it goes into the error too many requests loop for a few hours and then come out of it. All by itself.

My WP-Config file has

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https') {
    $_SERVER['HTTPS'] = 'on';
}

And my server config file is

fastcgi_cache_path /usr/share/nginx/fastcgi_cache levels=1:2 keys_zone=phpcache:100m max_size=10g inactive=60m use_temp_path=off;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

server {
    listen 8080 ;
    listen [::]:8080 ;
    server_name example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 8080 ;
    listen [::]:8080 ;

    autoindex off;

    client_max_body_size 128M;

    #Hide the nginx version.
    server_tokens off;

    #Hide the PHP version.
    fastcgi_hide_header X-Powered-By;
    proxy_hide_header X-Powered-By;

    add_header 'Content-Security-Policy' 'upgrade-insecure-requests';
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";

    large_client_header_buffers 4 64k;
    proxy_max_temp_file_size 0;

    root /home/site/wwwroot;
    index  index.php;
    server_name  www.example.com;

    set $skip_cache 1;

    #Security only allow these requests
    if ($request_method !~ ^(GET|HEAD|POST)$ ) {
      return 444;
    }

    location / {
      try_files $uri $uri/ /index.php?$args;
    }

    #Security don't allow any php files to run directly from the uploads folder
    location ~* /(?:uploads|files|wp-content|wp-includes|akismet)/.*.php$ {
        deny all;
        access_log off;
        log_not_found off;
    }

    #Security don't allow direct access to any dot files
    location ~ /\.(svn|git)/* {
        deny all;
        access_log off;
        log_not_found off;
    }
    location ~ /\.ht {
        deny all;
        access_log off;
        log_not_found off;
    }
    location ~ /\.user.ini {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Security hide any hidden files
     location ~ /\. {
         deny all;
     }

     #Security  hide any backup or SQL dump files
     location ~ ^.+\.(sql|bak|php~|php#|php.save|php.swp|php.swo)$ {
         return 404;
     }

    # POST requests and urls with a query string should always go to PHP
    if ($request_method = POST) {
        set $skip_cache 1;
    }
    if ($query_string != "") {
        set $skip_cache 1;
    }

    # Don't cache uris containing the following segments
    if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
        set $skip_cache 1;
    }

    # Don't use the cache for logged in users or recent commenters
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
        set $skip_cache 1;
    }

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    port_in_redirect off;
    absolute_redirect off;

    #deny access to xmlrpc
    location = /xmlrpc.php {
        deny all;
        error_page 403 http://www.google.com/;
    }

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /html/;
    }

    gzip on;

    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types image/svg+xml image/x-icon text/plain text/html text/xml text/css text/javascript application/xml application/xhtml+xml application/rss+xml application/javascript application/x-javascript application/x-font-ttf application/vnd.ms-fontobject font/opentype font/ttf font/eot font/otf image/vnd.microsoft.icon;

    location ~* \.(eot|ttf|woff|woff2|webmanifest)$ {
       add_header Access-Control-Allow-Origin *;
    }

    location ~* \.(css|js|ico|gif|jpeg|jpg|webp|png|svg|eot|otf|woff|woff2|ttf|ogg)$ {
       expires max;
    }

    location ~ [^/]\.php(/|$) {
        add_header 'Content-Security-Policy' 'upgrade-insecure-requests';
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
        add_header X-Frame-Options SAMEORIGIN;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";

        fastcgi_index index.php;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        fastcgi_cache phpcache;
        fastcgi_cache_valid 200 301 302 60m;
        fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
        fastcgi_cache_min_uses 1;
        fastcgi_cache_lock on;
        add_header X-FastCGI-Cache $upstream_cache_status;

        fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
        fastcgi_pass 127.0.0.1:9000;
        include fastcgi_params;
        fastcgi_param HTTP_PROXY "";
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param QUERY_STRING $query_string;
        fastcgi_intercept_errors on;
        fastcgi_connect_timeout         300;
        fastcgi_send_timeout           3600;
        fastcgi_read_timeout           3600;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
    }
}

Hoping someone has any debugging tips!

The output of curl -I when the redirect loop happens and when it doesn't is exactly the same

curl -I https://www.example.com
HTTP/2 200 
content-type: text/html; charset=utf-8
date: Fri, 21 Oct 2022 02:24:16 GMT
server: nginx
vary: Accept-Encoding
link: <https://www.example.com/wp-json/>; rel="https://api.w.org/"
link: <https://www.example.com/wp-json/wp/v2/pages/9346>; rel="alternate"; type="application/json"
link: <https://www.example.com/>; rel=shortlink
content-security-policy: upgrade-insecure-requests
strict-transport-security: max-age=31536000; includeSubDomains; preload
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-fastcgi-cache: HIT

Gqqnbig avatar
in flag
I have the same problem which can be solved by disabling fast cgi caching. My response headers have `X-FastCGI-Cache: HIT` and `X-Redirect-By: WordPress`.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.