how can I cache upstream by mime type in nginx

D
  • 1 Nov '22
hi there

My front end is nginx using reverse proxy work with my backend, I was
trying to cache images files only, but it seems doesn't work at all, the
*$no_cache* always output default value "proxy", which should be "0" when I
visit image files

here it is my config

map $upstream_http_content_type $no_cache {
> default proxy;
> "~*image" 0;
> }
> proxy_store on;
> proxy_temp_path /tmp/ngx_cache;
> proxy_cache_path /tmp/ngx_cache/pcache levels=1:2 use_temp_path=on
> keys_zone=pcache:10m inactive=14d max_size=3g;
> log_format upstreamlog '$server_addr:$host:$server_port
> $remote_addr:$remote_port $remote_user [$time_local] '
> '"$request" $status $request_length $body_bytes_sent [$request_time] '
> '"$http_referer" "$http_user_agent" "$http_x_forwarded_for" - '
> 'upstream: $upstream_addr - $upstream_status - upstream_response_time:
> $upstream_response_time $upstream_http_content_type $skip_cache :
> $no_cache';
> server{
> .....
> if ($skip_cache = false){
> set $skip_cache 0;
> }
> if ($no_cache = false){
> set $no_cache 0;
> }
> if ($request_method = POST) {
> set $skip_cache 1;
> }
> if ($query_string != "") {
> set $skip_cache 1;
> }
> if ($http_cache_control ~* "private") {
> set $skip_cache 1;
> }
> if ($upstream_http_cache_control ~* "private") {
> set $skip_cache 1;
> }
> location / {
> proxy_cache_key "$http_host$uri$is_args$args";
> proxy_cache pcache;
> add_header X-Cache-Status $upstream_cache_status;
> proxy_cache_bypass $http_pragma $http_authorization $skip_cache;
> proxy_no_cache $http_pragma $http_authorization $skip_cache $no_cache;
> proxy_pass http://$backend;
> access_log /dev/stdout upstreamlog;
> }
> }

the curl test output

> HTTP/1.1 200 OK
> Server: nginx
> Date: Sun, 30 Oct 2022 17:22:56 GMT
> Content-Type: image/jpeg
> Content-Length: 56769
> Connection: keep-alive
> Last-Modified: Tue, 19 Jul 2022 03:27:34 GMT
> ETag: "62d624a6-ddc1"
> Cache-Control: public, max-age=604800, s-maxage=1209600, stale-if-error=400
> X-Cache-Status: MISS
> Accept-Ranges: bytes

why *$upstream_http_content_type* map doesn't works as expected
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx/attachments/20221102/7ebda953/attachment.htm>
F
  • 1 Nov '22
On Wed, Nov 02, 2022 at 12:29:49AM +0800, Drweb Mike wrote:

Hi there,

> My front end is nginx using reverse proxy work with my backend, I was
> trying to cache images files only, but it seems doesn't work at all, the
> *$no_cache* always output default value "proxy", which should be "0" when I
> visit image files

$upstream_http_content_type is the Content-Type response header from the
upstream server, after nginx has sent a request to the upstream server.

Before nginx has sent a request to the upstream server, the variable
has no value.

If you want to use variables to decide whether nginx should handle a
request by looking in the cache before asking upstream, you should only
use variables that are available in the request, not ones that come
from upstream.

(Maybe you can use part of the request uri -- starts with /images/ or
ends with .jpg or .png, for example? It depends on what requests your
clients will be making.)

> why *$upstream_http_content_type* map doesn't works as expected

Your expectation is wrong.

Cheers,

    f
-- 
Francis Daly        francis at daoine.org
F
  • 1 Nov '22
On Tue, Nov 01, 2022 at 10:07:37PM +0000, Francis Daly wrote:
> On Wed, Nov 02, 2022 at 12:29:49AM +0800, Drweb Mike wrote:

Hi there,

> > My front end is nginx using reverse proxy work with my backend, I was
> > trying to cache images files only, but it seems doesn't work at all, the
> > *$no_cache* always output default value "proxy", which should be "0" when I
> > visit image files

> If you want to use variables to decide whether nginx should handle a
> request by looking in the cache before asking upstream, you should only
> use variables that are available in the request, not ones that come
> from upstream.
> 
> (Maybe you can use part of the request uri -- starts with /images/ or
> ends with .jpg or .png, for example? It depends on what requests your
> clients will be making.)

proxy_cache_bypass (http://nginx.org/r/proxy_cache_bypass) is "nginx
should not look in the cache for this response; go straight to upstream".

proxy_no_cache (http://nginx.org/r/proxy_no_cache) is "nginx should not
save this response from upstream to the cache".

Maybe you want to never use proxy_cache_bypass; and use proxy_no_cache
to make sure that only the things that should be written to the
cache, are written there? You could do proxy_no_cache based on
$upstream_http_content_type; and that any other requests will look in
the cache, see nothing there, and go to upstream anyway.

Cheers,

    f
-- 
Francis Daly        francis at daoine.org