【问题标题】:nginx; return response code if a file exists by using try_files onlynginx;如果仅使用 try_files 存在文件,则返回响应代码
【发布时间】:2013-05-17 14:09:34
【问题描述】:

自从IfIsEvil 以来,我一直在尝试使用指令try_files 设置配置,以便维护页面与响应代码503 一起显示,对于任何URI 无一例外,即包括php 页面,如果存在维护文件。

我的配置有两个问题:

  1. 维护页面不显示 php URI。
  2. 如果maintenance.html文件存在,则不返回响应码503。

我见过类似的问题[1],[2],但没有一个解决方案只使用try_files(而不是使用if 指令)并且无条件地提供响应代码为503 的维护页面,如果存在相应的文件。这样的解决方案可行吗?

以下是我当前无法使用的 conf 文件。它不包含 503 响应代码设置,因为我不明白它应该去哪里才能使其按上述方式工作。

worker_processes            1;

error_log                   /var/log/nginx/error.log debug;

events {
    worker_connections      1024;
}

http {
    include                 mime.types;
    default_type            application/octet-stream;

    index                   index.php index.html index.htm;

    server {
        listen                  80;
        server_name             rpi;
        root                    /www;

        location / {
            try_files           /maintenance.html $uri $uri/ /index.php?$args;

            # pass the PHP scripts to FastCGI server
            location ~ \.php$ {
                try_files           $uri =404;
                fastcgi_pass        unix:/run/php-fpm/php-fpm.sock;
                fastcgi_index       index.php;
                include             fastcgi.conf;
            }
        }
    }
}

我想我的问题也可以这样表述:try_files 可以用作if 控制结构吗?如果不是单独使用,是否可以根据上述目标与其他指令结合使用,不包括if 指令?

编辑:以下是使用if 的解决方案,我目前正在使用它,将其包含在服务器部分中:

error_page              503 @maintenance;

if (-f $document_root/maintenance.html) {
        return          503;
}

location @maintenance {
        try_files       /maintenance.html =404;
}

【问题讨论】:

    标签: nginx


    【解决方案1】:

    非常好的问题!但是,除非您调用某种设置正确响应代码的脚本,否则这是不可能的。

    仅使用 nginx 且没有 if 的有效解决方案

    try_files directive 仅对最后一条语句执行内部重定向。但是我们可以将它与index directive 结合起来并强制进行内部重定向。

    # This will be the HTML file to display for the 503 error.
    error_page 503 /maintenance/maintenance.html;
    
    # Let nginx know that this particular file is only for internal redirects.
    location = /maintenance/maintenance.html {
      internal;
    }
    
    # Any request that starts with the maintenance folder is 503!
    location ^~ /maintenance/ {
      return 503;
    }
    
    # Instead of checking if a file exists and directly delivering it we check
    # if a certain directory exists and trigger our index directive which will
    # perform an internal redirect for us.
    location / {
      expires epoch;
      try_files /maintenance/ $uri $uri/ /index.php?$args;
    }
    

    这种方法有什么缺点吗?

    • 实际的 301 重定向到目录,而不是停留在相同的 URL(搜索引擎)。
    • 浏览器缓存 301 重定向可能是一个问题,这就是我将 expires epoch 添加到位置块的原因。

    其他解决方案?

    通过nginx配置文件

    与其创建一个 HTML 文件,不如创建一个 nginx 配置文件并简单地重新加载进程?

    • 更好的性能!
    • 更容易理解!
    • 没有副作用!

    nginx 配置可能如下所示(注意这个if 一点也不邪恶):

    error_page 503 /maintenance.html;
    
    location / {
      include maintenance.conf;
      if ($maintenance = 1) {
        return 503;
      }
      try_files $uri $uri/ /index.php?$args;
    }
    

    maintenance.conf 文件的内容:

    set $maintenance 0;
    

    如果你想激活维护模式(在你的 shell 中):

    echo set $maintenance 1;> maintenance.conf && service nginx reload
    

    更高级的shell朋友 你甚至可以用这个扩展一个初始化脚本,例如 my LSB compliant one 通过替换文件末尾的以下块:

    *)
      echo "Usage: ${NAME} {force-reload|reload|restart|start|status|stop}" >&2
      exit 1
    ;;
    

    使用以下块:

    maintenance)
      echo "set $maintenance 1;" > /etc/nginx/maintenance.conf && service nginx reload;
    ;;
    
    production)
      echo "set $maintenance 0;" > /etc/nginx/maintenance.conf && service nginx reload;
    ;;
    
    *)
      echo "Usage: ${NAME} {force-reload|reload|restart|start|status|stop|maintenance|production}" >&2
      exit 1
    ;;
    

    现在您可以简单地执行以下命令(包括自动完成)进入维护模式:

    service nginx maintenance
    

    或以下内容重新投入生产:

    service nginx production
    

    带有脚本/PHP文件

    另一个非常简单的方法是使用处理它的 PHP 文件。

    location / {
        try_files /maintenance.php $uri $uri/ /index.php?$args;
    }
    

    您的 PHP 文件看起来与您的 HTML 文件一模一样,您只需在其开头添加以下内容(假设 PHP 5.4+):

    <?php http_response_code(503) ?><!doctype html>
    <html>
    <head>
    <!-- ... more html ... -->
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-29
      • 2014-04-26
      • 1970-01-01
      • 2020-01-20
      • 1970-01-01
      • 2017-02-10
      • 2011-10-19
      相关资源
      最近更新 更多