1

I'm using Nginx on CentOS with a Rails server. I'm confused about how headers get set. If Nginx sets headers and the applicatino server (Ruby on Rails in this case), which one wins out? I have this Nginx server block

server {
  listen 80;
  server_name www.example.com;
  root /home/rails/scale_production/public; # I assume your app is located at this location

  location / {
    proxy_pass http://scale; # match the name of upstream directive which is defined above
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    if ($request_uri ~* "($\/image\/.*)|(.*\.(ico|gif|jpe?g|png)$)") {
      expires 60d;
      access_log off;
      add_header Pragma public;
      add_header Cache-Control "public";
      break;
    }
  }

  location ~* ^/assets/ {
    # Per RFC2616 - 1 year maximum expiry
    expires 1y;
    add_header Cache-Control public;

    # Some browsers still send conditional-GET requests if there's a
    # Last-Modified header or an ETag header even if they haven't
    # reached the expiry date sent in the Expires header.
    add_header Last-Modified "";
    add_header ETag "";
    break;
  }

However when I call a URL that matches one of my regex's, I'm not seeing the cache headers getting set ....

localhost:tmp davea$ curl -I "http://www.example.com/people/image/27"
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Sat, 03 Mar 2018 18:20:43 GMT
Content-Type: image/jpeg; charset=binary
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Expires: Sun, 03 Mar 2019 18:20:43 GMT
Content-Disposition: inline; filename="Bill Smith"
Content-Transfer-Encoding: binary
Cache-Control: private
ETag: W/"b0c3f986a9c7f967e58733702e71a395"
X-Request-Id: 2f9728bb-3b6f-4d67-9344-afc1e29cacd5
X-Runtime: 0.007781

So I'm wondering why this happens . Am I doing something wrong in my block or are there headers getting set in my application server that are overriding the Nginx headers?

4
  • You're not using Nginx optimally. Instead of an "if this is an image" within the location block make a new location block that has the regex in it. Use a website like regex101 to make sure you have it correct. I also add headers to debug my locations and such - set headers in a few places and see which ones are output.
    – Tim
    Mar 3, 2018 at 18:47
  • So I'm clear, your talking about cleaning things up, but it wouldn't influence how headers are added, would it?
    – Dave
    Mar 3, 2018 at 19:13
  • It would in this case, because you would no longer have Rails serving your static content. Which is the whole point of using nginx in the first place. So, yes, you need to clean this up. Then you can worry about whether headers get added to static content... Mar 3, 2018 at 19:56
  • In the case of the URL I listed, "example.com/people/image/27", this is actually not calling out to an image on the file-system, but rather a Rails method that serves binary data from a database.
    – Dave
    Mar 3, 2018 at 20:31

1 Answer 1

0

Your headers are not set because of an error in that regex. Remove the first occurence of $. A regex containing $ will only match if there is a line ending at exactly this position.

Regarding header overwriting. It's not like the same headers come from browser, get through server and are returned back to the same browser - it wouldn't make sense.

There are request headers - they come from browser, you can overwrite these in nginx before passing to app server. (Main examples: Host, Accept, User-Agent).

And there are response headers - they are created by app server, you can overwrite these in nginx before passing a reponse to the browser. (This includes Expires etc.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .