Expires header based on dynamic Content-Type in nginx

I have a PHP site where some content is user generated. For example, users can upload photos that are resizable and can be requested. I would like to specify a header Expires

(for caching) based on the MIME type ( Content-Type

response header) in my nginx config.

This is my current config (my host automatically adds http{}

and server{}

):

charset utf-8;

types {
    text/css            css;
    text/javascript     js;
}

gzip on;
gzip_types text/html text/css text/javascript application/json image/svg+xml;

location / {
    if (!-e $request_filename) {
        rewrite  .  /index.php last;
        break;
    }


    set $expire 0;

    if ($upstream_http_content_type = image/jpeg) { set $expire 1; }
    if ($upstream_http_content_type = image/png) { set $expire 1; }
    if ($upstream_http_content_type = image/gif) { set $expire 1; }
    if ($upstream_http_content_type = image/svg+xml) { set $expire 1; }
    if ($upstream_http_content_type = text/css) { set $expire 1; }
    if ($upstream_http_content_type = text/javascript) { set $expire 1; }

    if ($expire = 1) {
        expires max;
    }
}

      

This works for static files (like files .png

- they get the correct header Expires

), but it doesn't affect the dynamically generated content from the index.php

(no Expires

) header in any way . Does anyone know what I am doing wrong?

+3


source to share


1 answer


There is location

no room in your block when you pass a request to a php web app, so I can assume that you are doing it elsewhere, for example in a block location

like this:

location /index.php {
   # your code
}

      

With your config, when a user asks for a static file that exists, the first directive is if

not evaluated and everything goes well. Problems start when the user requests dynamic files and then nginx enters your first block if

:

if (!-e $request_filename) {
    rewrite  .  /index.php last;
    break;
} 

      

So what happened? Are you using a last

directive flag rewrite

and what does the nginx doc say about it?

last - ends processing of the current rewrite directives and restarts the process (including rewriting) looking for a match in the URI from all available places.

According to this specification, when the file is dynamic, you have done a correspondence index.php

, and execution leaves a block if

and even a whole block location

, and the next block if

to check content-type

is not even checked. I suppose it will find location

for url /index.php

and there you won't install expires max

.



Do you understand this expansion of your problem?

The resolution to this too will move / copy your serial block if

to check content-type

that place where your configuration passes performance in php (index.php) web application ... or remove the flag last

from rewrite

, if it does not cause any other problems.

Okey, since I promised a little fix for your conf file: change the block location

to two:

location /index.php {
   if ($upstream_http_content_type ~ "(image/jpeg)|(image/png)|(image/gif)|(image/svg+xml)|(text/css)|(text/javascript)") {
      expires max;
   }
   if ($sent_http_content_type ~ "(image/jpeg)|(image/png)|(image/gif)|(image/svg+xml)|(text/css)|(text/javascript)") {
      expires max;
   }
}

location / {
   if ($upstream_http_content_type ~ "(image/jpeg)|(image/png)|(image/gif)|(image/svg+xml)|(text/css)|(text/javascript)") {
      expires max;
   }
   if ($sent_http_content_type ~ "(image/jpeg)|(image/png)|(image/gif)|(image/svg+xml)|(text/css)|(text/javascript)") {
      expires max;
   }
   try_files $uri /index.php =404;
}

      

The first block location

is for your index.php

and dynamic response, and the second is for static files. In the second, we add the header expires max

as the upstream header and as the standard header (just to be sure). I am using one block here if

for all the types that you define in your configuration, matching the regex pattern. At the end we use a directive try_files

which means that if a url based static file can be retrieved, it will be fetched and otherwise try url / index.php or just return with http 404. The first location block is for the url only /index.php

. I didn't find anywhere in your config directiveroot

which should point to the root folder of your application. Try adding this as well ( root doc ).

Hope this solves your problems.

+1


source







All Articles