Nginx反向代理:如何根据响应内容特定词汇禁用缓存?
Absolutely, you can pull this off without touching your backend code—Nginx has several flexible tools to inspect response content and adjust cache headers on the fly. Let’s break down the most practical approaches tailored to your needs:
1. Using ngx_lua (Recommended for Performance)
The ngx_lua module (bundled with OpenResty) is the most efficient way to handle content-based logic in Nginx. Here's how to set it up:
Step 1: Ensure ngx_lua is installed
If you’re using OpenResty, this module is included by default. For standard Nginx, compile it with --add-module=path/to/ngx_lua during installation.
Step 2: Configure Nginx
Add this to your server or location block:
location / { proxy_pass http://your-backend-server; # Only process text/html responses to save resources set $no_cache 0; if ($content_type ~* text/html) { set $no_cache 1; } # Inspect response body and adjust cache headers body_filter_by_lua_block { local content_chunk = ngx.arg[1] local target_word = "your-specific-term" # Replace with your target vocabulary # Check if the chunk contains the target word if string.find(content_chunk, target_word) then # Override headers to disable caching ngx.header["Cache-Control"] = "no-store, no-cache, must-revalidate" ngx.header["Pragma"] = "no-cache" ngx.header["Expires"] = "0" end } # Apply cache bypass rules proxy_cache_bypass $no_cache; proxy_no_cache $no_cache; }
Notes:
- For large responses, check only a portion of the content (e.g., first 10KB) to avoid high memory usage:
string.find(string.sub(content_chunk, 1, 10240), target_word) - Use
string.lower(content_chunk)if you need case-insensitive matching.
2. Using Embedded Perl
If you prefer Perl, Nginx’s ngx_http_perl_module can handle content inspection too.
Step 1: Enable the Perl module
Compile Nginx with --with-http_perl_module and ensure Perl is installed on your server.
Step 2: Configure Nginx
Add this to your config:
http { server { location / { proxy_pass http://your-backend-server; perl_body_filter 'sub { my ($r, $chunk, $eof) = @_; my $target_word = "your-specific-term"; # Check for the target word in the response chunk if (index($chunk, $target_word) != -1) { $r->header_out("Cache-Control", "no-store, no-cache, must-revalidate"); $r->header_out("Pragma", "no-cache"); $r->header_out("Expires", "0"); } return $chunk; }'; } } }
Notes:
- Perl filters are slightly slower than Lua for high-traffic sites, so monitor performance if you use this approach.
- The
$eofflag indicates the end of the response—you can use it to run final checks if needed.
3. Piping Response to a PHP Script
If you’re more comfortable with PHP, you can forward the backend response to a PHP script for processing, then send the modified response to the client.
Configure Nginx
location / { # Fetch backend response and store it temporarily proxy_pass http://your-backend-server; proxy_store on; proxy_store_access user:rw group:rw all:r; set $temp_response $request_filename; # Pass the temporary file to PHP for processing fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_param SCRIPT_FILENAME /path/to/your/content-processor.php; fastcgi_param TEMP_RESPONSE_FILE $temp_response; }
Example PHP Script (content-processor.php)
<?php $temp_file = $_SERVER['TEMP_RESPONSE_FILE']; $content = file_get_contents($temp_file); $target_word = "your-specific-term"; // Check for the target word and adjust headers if (strpos($content, $target_word) !== false) { header("Cache-Control: no-store, no-cache, must-revalidate"); header("Pragma: no-cache"); header("Expires: 0"); } // Send the original content to the client echo $content; // Clean up the temporary file unlink($temp_file); ?>
Notes:
- This approach adds extra overhead due to file I/O and PHP processing, so it’s best suited for low-traffic environments.
- Adjust the PHP-FPM socket path and script location to match your server setup.
4. Modifying Nginx Source Code
If you’re comfortable compiling Nginx from source, you can add custom logic directly into the proxy module.
Approach:
- Download the Nginx source code and navigate to
src/http/modules(wherengx_http_proxy_module.cis located). - Locate the function that processes backend response bodies—look for
ngx_http_proxy_process_bodyor similar. - Insert code to read response chunks, check for your target word, and modify cache headers if a match is found:
u_char *target_word = (u_char *)"your-specific-term"; size_t word_length = ngx_strlen(target_word); // Check if the chunk contains the target word if (ngx_strstr(chunk->data, target_word, word_length, chunk->len) != NULL) { // Add/override Cache-Control header ngx_table_elt_t *cache_control = ngx_list_push(&r->headers_out.headers); cache_control->hash = 1; ngx_str_set(&cache_control->key, "Cache-Control"); ngx_str_set(&cache_control->value, "no-store, no-cache, must-revalidate"); // Repeat for Pragma and Expires headers ngx_table_elt_t *pragma = ngx_list_push(&r->headers_out.headers); pragma->hash = 1; ngx_str_set(&pragma->key, "Pragma"); ngx_str_set(&pragma->value, "no-cache"); }
- Recompile Nginx with your modified code and test thoroughly.
Notes:
- This requires knowledge of C and Nginx’s internal API—only attempt this if you’re confident with low-level modifications.
- Keep track of your changes so you can reapply them when updating Nginx.
内容的提问来源于stack exchange,提问作者POMATu

