What in nginx determines what goes to rails and wh

2019-08-05 10:40发布

I have a nginx + thin + Rails 3.2 setup. Currently I am trying to setup nginx so it can serve cached pages directly.

However nginx still pass *.html request to Rails in the following nginx configuration files. The html files exists in public folder, and nginx does find them, just that they are still passed to Rails.

upstream site {
  server unix:/home/site/deploy/site/shared/pids/thin.0.sock;
}

server {
  listen 80;
  server_name www.example.com;
  rewrite ^(/.*) http://example.com$1 permanent;
}

# asset server
server {
  listen 80;
  server_name assets.example.com;
  expires max;
  add_header Cache-Control public;
  charset utf-8;
  root   /home/site/deploy/site/current/public/;
}

# frontend
server {
  listen 80;
  server_name .example.com;
  charset utf-8;

  root   /home/site/deploy/site/current/public/;
  index  index.html;

  location ~* ^.+.(jpg|jpeg|gif|png|swf|zip|rar|doc|xls|exe|pdf|ppt|txt|tar)$ {
    root /home/site/deploy/site/current/public/;
    expires max;
    break;
  }

  # serve static files
  if (-f $request_filename) {
    break;
  }

  gzip on;

  location / {
    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;

    if (-f $request_filename) {
      break;
    }

    if (-f $document_root/cache/$host/$uri/index.html) {
      rewrite (.*) /cache/$host/$1/index.html break;
    }

    if (-f $document_root/cache/$host/$uri.html) {
      rewrite (.*) /cache/$host/$1.html break;
    }

    if (-f $document_root/cache/$host/$uri) {
      rewrite (.*) /cache/$host/$1 break;
    }

    proxy_pass http://site;
    break;
  }
}

I am new to nginx, and this configuration file is copied from previous projects I have not worked on, so this is probably a very newbie question.

2条回答
Summer. ? 凉城
2楼-- · 2019-08-05 11:24

To allow nginx to serve static cached pages you need to use try_files, let me share the config:

upstream site {
  server          unix:/home/site/deploy/site/shared/pids/thin.0.sock fail_timeout=0;
}

server {
  listen          80;
  server_name     www.example.com;
  rewrite ^(/.*)  http://example.com$1 permanent;
}

server {
  listen          80;
  server_name     example.com;
  charset         utf-8;

  root            /home/site/deploy/site/current;
  try_files       $uri/index.html $uri @thin;

  gzip on;

  location @thin {
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  Host $http_host;
    proxy_redirect    off;
    proxy_pass        http://site;
  }

  location ~* ^.+.(jpg|jpeg|gif|png|swf|zip|rar|doc|xls|exe|pdf|ppt|txt|tar)$ {
    root             /home/site/deploy/site/current/public/;
    expires          max;
    break;
  }
}
查看更多
冷血范
3楼-- · 2019-08-05 11:29

Here is a more general theoretical answer (SO editors rejected my edit to explain in the answer above.):

Nginx has a ngx_static module which is on by default. This module runs at end of the content phase. It will serve static files if no other content command in that location block can work in the request. It will also only work if the uri does not end with slash.

So to serve static files, one need to make sure the uri is a valid path name by the end of content phase, and there is no other content phase command that can serve stuff in the same location block.

In my case, I want to access cached page, I can use try_files to rewrite the uri. try_files works in a phase just before the content phase, which will check for existence of files. If one of them exist, then the uri is changed to that file. Then in the content phase it will be served.

What if I want to serve static file if it exists, or serve dynamic content if it does not? Usually serving dynamic content will prevent static file to be served. In this case a different location block can be used. If no static file is found during try_files, we jump to another location block (in the example @thin, where all dynamic contents are served. But if static file exists, we stay in the original location block, and as we enter the content phase, since there is no other content serving command, the static file is served.

查看更多
登录 后发表回答