Understanding location blocks and try files

AD7six nginx-forum at nginx.us
Fri Jan 24 16:18:07 UTC 2014

> > I did also try using the front controller as a 404 handler which worked
> > exactly how I am trying to get things to work _except_ of course
> > from the front controller is a http 404.

> Why "of course"?

> http://nginx.org/r/error_page

I said "of course" as when processed as a 404 - it didn't seem possible to
modify the http response code. So all content was served as desired BUT as a
404, however I'd missed this in the docs:

> If an error response is processed by a proxied server or a FastCGI server,
and the server may return different response codes (e.g., 200, 302, 401 or
404), it is possible to respond with the code it returns:

> error_page 404 = /404.php;

Therefore using the following config:

server {
    listen 80; 
    server_name nginx.dev *.nginx.dev;

    try_files $uri $uri.html;
    error_page 404 = @app; <-

    root /etc/nginx/www;
    index index.php index.html index.htm;

    send_timeout 600s;

    location @app {
        fastcgi_param   QUERY_STRING        $query_string;

        add_header section "app"; <-

    location ~* \.(?:manifest|appcache|html?|xml|json)$ {
      expires -1; 

      add_header section "static json files"; <-


Gives the folllowing results:

$ curl -I http://nginx.dev/doesnotexist.json
HTTP/1.1 200 OK
Server: nginx/1.4.4
Date: Fri, 24 Jan 2014 15:39:19 GMT
Content-Type: text/html
Connection: keep-alive
Vary: Accept-Encoding
section: app <-

$ curl -I http://nginx.dev/static.json
HTTP/1.1 200 OK
Server: nginx/1.4.4
Date: Fri, 24 Jan 2014 15:40:25 GMT
Content-Type: application/json
Content-Length: 20
Last-Modified: Wed, 22 Jan 2014 18:01:51 GMT
Connection: keep-alive
ETag: "52e0078f-14"
Expires: Fri, 24 Jan 2014 15:40:24 GMT
Cache-Control: no-cache
section: static json files <-
Accept-Ranges: bytes

Which is _exactly_ what I'm aiming for, it means it's possible to define
rules for static files without the risk of dynamically served content with
the same url pattern being inaccessible.

> I suspect that that's pretty much required, based on the idea that generic
= slow, specific = fast; and nginx being built to be fast.

Optimizing frontend performance is pretty easy, doesn't require detailed
analysis and has signifiant benefits (especially for mobile devices). To a
certain extent it doesn't matter if the webserver is fast if it is having to
serve more work because of unoptimized frontend performance (or though the
absense of other headers meaning the application simply doesn't work). 

It should be an obvious and easy step to optimize the serving of an
application's static files rather than (as it had seemed right up until your
last post) an arduous cumbersome fragile process which can lead to
applications breaking. It doesn't matter if an image is /here.png
/over/here.png or /way/way/over/here.png - if it's a static file it should
be served with appropriate cache headers. needing to wrap rules for static
files in all locations where they may occur is in many cases not viable -
since even with a structured application the files may be in sufficiently
varied locations to always overlap with dynamic requests.

> I suspect I'm missing something obvious, but why can't you do this? If you
want the effect of "expires max", why do you care whether you are serving
from file, from cache, or from php directly?

Serving files with php is slower, depending on exactly what it's doing
possibly a lot slower, than letting the webserver do it. At the very least
it means reimplementing cache header handling and partial responses in the
application layer. This is not a point to be taken lightly - I'd go as far
as to say doing that when you don't need to is a flat out bad idea.

Here is an example where the same url may or may not be a static file
That's a pattern which is used by many (most?) web frameworks - whereby
static files are used if they exist but handled transparently if they do

If it could only be static OR dynamic that would mean one of:

1) The file must always be served by php with specific headers.
2) it is impossible to generate the file dynamically, but if it exists it
has specific headers.
3) It is possible to generate the file dynamically, but will have no
specific headers once generated.
4) Additional server config is required to cache the response from php
(hadn't really thought of that - but that's quite cumbersome)

None of which are attractive.

But now, that's all moot =). Thanks very much for your help identifying that
a dynamic response can be used as a 404 handler _and_ define the response
code. I may propose a change to make that more obvious to future



Posted at Nginx Forum: http://forum.nginx.org/read.php?2,246713,246797#msg-246797

More information about the nginx mailing list