From 2b05c4e544372287efb91a46612868cd77ff5424 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Tue, 27 Jan 2026 14:23:46 +0100 Subject: [PATCH] Cache ALL requests Completely hallucinated God help us --- nginx.conf | 46 ++++++++++++++++++++++++++++++++++++---------- test.sh | 14 ++++++++++++++ 2 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 test.sh diff --git a/nginx.conf b/nginx.conf index a4da609..c848f96 100644 --- a/nginx.conf +++ b/nginx.conf @@ -28,9 +28,25 @@ http { listen 3000; location / { + # Return immediately for OPTIONS so cache/proxy are never involved (avoids "if" affecting cache) + if ($request_method = 'OPTIONS') { + add_header Access-Control-Allow-Origin *; + add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH"; + add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Cache,X-NoCache,X-Status"; + add_header Access-Control-Max-Age 86400; + return 204; + } set $backend_base ""; - # Decode url, build upstream URL, strip our "url=". Force that URI to upstream (variable proxy_pass can send original request URI otherwise) + set $body_for_cache_key ""; + # Decode url, build upstream URL, strip our "url=". Read body for cache key (so POST is keyed by body). rewrite_by_lua_block { + ngx.req.read_body() + local body = ngx.req.get_body_data() + if not body and ngx.req.get_body_file() then + local f = io.open(ngx.req.get_body_file(), "rb") + if f then body = f:read("*a"); f:close() end + end + ngx.var.body_for_cache_key = ngx.md5(body or "") local enc = ngx.var.url_encoded local decoded = (enc and enc ~= "") and ngx.unescape_uri(enc) or ngx.var.arg_url or "" if decoded == "" then @@ -62,8 +78,16 @@ http { proxy_set_header Host $proxy_host; proxy_ssl_server_name on; - # Strip upstream CORS so we only send our own (duplicate = browser reject) + # Cache key is built from variables; must fit in proxy_buffer_size (body part is MD5 in Lua) + proxy_buffer_size 16k; + proxy_buffering on; + proxy_buffers 4 256k; + proxy_busy_buffers_size 256k; + proxy_max_temp_file_size 1024m; + + # Strip upstream CORS and Set-Cookie so we only send our own CORS and don't leak cookies proxy_hide_header Access-Control-Allow-Origin; + proxy_hide_header Set-Cookie; proxy_hide_header Access-Control-Allow-Methods; proxy_hide_header Access-Control-Allow-Headers; proxy_hide_header Access-Control-Expose-Headers; @@ -75,17 +99,19 @@ http { add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Cache,X-NoCache,X-Status" always; add_header Access-Control-Expose-Headers "X-Cache-Status" always; - # Handle preflight OPTIONS requests - if ($request_method = 'OPTIONS') { - return 204; - } - proxy_cache api_cache; + proxy_cache_methods GET HEAD POST; + proxy_cache_key $backend_base$request_method$uri$is_args$args$body_for_cache_key; proxy_cache_valid 200 201 202 203 204 205 206 207 208 226 365d; - proxy_ignore_headers Cache-Control Expires; + # Ignore headers that would prevent storing the response + proxy_ignore_headers Cache-Control Expires Set-Cookie Vary X-Accel-Expires X-Accel-Redirect; - proxy_cache_bypass $http_x_nocache; - proxy_no_cache $http_x_nocache; + # Bypass cache for this request (and do not store): send X-NoCache or X-Cache-Invalidate (any value) + set $skip_cache 0; + if ($http_x_nocache != "") { set $skip_cache 1; } + if ($http_x_cache_invalidate != "") { set $skip_cache 1; } + proxy_cache_bypass $skip_cache; + proxy_no_cache $skip_cache; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..df238c8 --- /dev/null +++ b/test.sh @@ -0,0 +1,14 @@ +docker compose down + +# Rebuild so current nginx.conf is copied into the image (no volume mount for config) +docker compose up -d --build +sleep 5 + +curl 'http://localhost:3000/?url=https://clickhouse-zkill.site.quack-lab.dev/?database=zkill&default_format=JSON' -H 'accept: */*' -H 'accept-language: en-US' -H 'authorization: Basic emtpbGxfcm9fdXNlcjp2Mk05WmdqWWtxeXB5UzRuZTlKdEs3QllwNjk0MnVqdQ==' -H 'content-type: text/plain; charset=utf-8' -H 'origin: http://localhost:8080' -H 'priority: u=1, i' -H 'referer: http://localhost:8080/' -H 'sec-ch-ua: "Not_A Brand";v="99", "Chromium";v="142"' -H 'sec-ch-ua-mobile: ?0' -H 'sec-ch-ua-platform: "Windows"' -H 'sec-fetch-dest: empty' -H 'sec-fetch-mode: cors' -H 'sec-fetch-site: cross-site' -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Cursor/2.4.21 Chrome/142.0.7444.235 Electron/39.2.7 Safari/537.36' --data-raw $'\n SELECT\n corporation_name,\n alliance_name,\n uniq(killmail_id) as kills_participated,\n uniq(character_name) as members_involved\n FROM zkill.killmail_attackers\n WHERE 1=1\n \n GROUP BY corporation_name, alliance_name\n ORDER BY kills_participated DESC\n ' +curl 'http://localhost:3000/?url=https://clickhouse-zkill.site.quack-lab.dev/?database=zkill&default_format=JSON' -H 'accept: */*' -H 'accept-language: en-US' -H 'authorization: Basic emtpbGxfcm9fdXNlcjp2Mk05WmdqWWtxeXB5UzRuZTlKdEs3QllwNjk0MnVqdQ==' -H 'content-type: text/plain; charset=utf-8' -H 'origin: http://localhost:8080' -H 'priority: u=1, i' -H 'referer: http://localhost:8080/' -H 'sec-ch-ua: "Not_A Brand";v="99", "Chromium";v="142"' -H 'sec-ch-ua-mobile: ?0' -H 'sec-ch-ua-platform: "Windows"' -H 'sec-fetch-dest: empty' -H 'sec-fetch-mode: cors' -H 'sec-fetch-site: cross-site' -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Cursor/2.4.21 Chrome/142.0.7444.235 Electron/39.2.7 Safari/537.36' --data-raw $'\n SELECT\n corporation_name,\n alliance_name,\n uniq(killmail_id) as kills_participated,\n uniq(character_name) as members_involved\n FROM zkill.killmail_attackers\n WHERE 1=1\n \n GROUP BY corporation_name, alliance_name\n ORDER BY kills_participated DESC\n ' + +sleep 3 +docker compose logs +docker compose down + +head result.json \ No newline at end of file