2
\$\begingroup\$

This config has 3 main features but there seems to be a lot of duplication and I wonder if I could improve it.

1 Detect all pngs and jpgs in static/img and try a webp version if the requesting browser supports it

2 Detect non-ES6 supporting browsers and serve site.babel.js, otherwise serve site.js which is un-babelified

3 Proxy all other requests to a node app running on port 3000

upstream node_upstream {
    server node:3000;
    keepalive 64;
}

#Required since SSL termination is higher up at the AWS load balancer
map $http_x_forwarded_proto $is_https {
  default off;
  https on;
}

map $http_accept $webp_suffix {
    default   "";
    "~*webp"  ".webp";
}

map $http_user_agent $script_file {
    default                                 "site.js";
    "~MSIE"                                 "site.babel.js";
    "~Trident"                              "site.babel.js";
    "~Opera.*Version/[0-9]\."               "site.babel.js";
    "~Opera.*Version/[0-1][0-9]\."          "site.babel.js";
    "~Opera.*Version/2[0-1]\."              "site.babel.js";
    "~AppleWebKit.*Version/[0-9]\..*Safari" "site.babel.js";
    "~Chrome/[0-9]\."                       "site.babel.js";
    "~Chrome/[0-2][0-9]\."                  "site.babel.js";
    "~Chrome/3[0-3]\."                      "site.babel.js";
    "~Chrome/4[0-3]\."                      "site.babel.js";
    "~Edge/1[0-3]\."                        "site.babel.js";
}

server {
    root /var/www/html/src;

    gzip on;

    # AWS traffic will come via a load balancer with the original protocol stored in http_x_forwarded_proto
    # If this is set to http then we need to redirect any request onto https equivalent
    # Should be ignored in non AWS environment as http_x_forwarded_proto should not be set
    if ($http_x_forwarded_proto = "http") {
      rewrite ^(.*)$ https://$http_host$1 permanent;
    }

    location = /static/site.js {
        root  /var/www/html/src;
        expires 1y;
        access_log off;
        add_header Cache-Control "public";
        try_files /static/$script_file =404;
    }

    location ~* ^/static/img/.+\.(png|jpg)$ {
        root /var/www/html/src;
        add_header Vary Accept;
        expires 1y;
        access_log off;
        add_header Cache-Control "public";
        try_files $uri$webp_suffix $uri =404;
    }

    location ~* ^/static/.*$
    {
        root  /var/www/html/src;
        expires 1y;
        access_log off;
        add_header Cache-Control "public";
    }

    location / {
        proxy_redirect off;
        proxy_set_header   X-Real-IP            $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_set_header   Host                   $http_host;
        proxy_set_header   X-NginX-Proxy    true;
        proxy_set_header   Connection "";
        proxy_http_version 1.1;
        proxy_pass         http://node_upstream;
    }

    error_log /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
}
\$\endgroup\$
2
\$\begingroup\$

root

The root directive is inherited. You have the same statement in the server block, and repeated in a number of location blocks. Only the first statement is necessary. See this document for details.

location ~* ^/static/.*$

This can be replaced by the prefix location:

location /static/ { ... }

The prefix location is more efficient than the regular expression location. The precedence order is different, but that does not affect your current configuration. See this document for details.

rewrite ^(.*)$ https://$http_host$1 permanent;

You can replace this with a return statement, thus eliminating a regular expression.

return 301 https://$http_host$request_uri;

Nested location blocks

A number of statements are common to three location blocks, all of which represent URIs that begin with /static/. The expires, access_log and add_header directives are inherited.

You could restructure your locations as follows:

location /static/ {
    root  /var/www/html/src;
    expires 1y;
    access_log off;
    add_header Cache-Control "public";

    location = /static/site.js {
        try_files /static/$script_file =404;
    }
    location ~* ^/static/img/.+\.(png|jpg)$ {
        add_header Vary Accept;
        add_header Cache-Control "public";
        try_files $uri$webp_suffix $uri =404;
    }
}
location / {
    ...
}

This would improve efficiency as URIs which do not begin with /static/ will not need to be checked against the regular expressions.

The add_header directive has an additional inheritance rule. See this document for details.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks, nested location blocks is exactly the kind of thing i was looking for. \$\endgroup\$ – Steve Mar 3 '19 at 22:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.