LoginSignup
2
2

More than 5 years have passed since last update.

nginx で location の中に limit_except と try_files を併記すると 404 Not Found になる件

Posted at

upstream を準備する

GET /appPOST /app に応答する単純な Sinatra アプリを準備。

$ rbenv local 2.3.0
$ cat <<EOF > Gemfile
source 'https://rubygems.org'

ruby '2.3.0'

gem 'sinatra'
gem 'thin'
gem 'rack-cors', require: 'rack/cors'
EOF
$ bundle install
$ cat <<EOF > app.rb
require 'sinatra'

get '/app' do
  'GET'
end

post '/app' do
  'POST'
end
EOF
$ cat <<EOF > config.ru
require './app'
run Sinatra::Application
EOF
$ bundle exec rackup -p 3000
$ curl http://localhost:3000/app
GET
$ curl -X POST http://localhost:3000/app
POST

try_files を使った内部リダイレクトを準備する

URLパスに対応するファイルがなければ upstream にリダイレクトする設定。

$ curl -L -O http://downloads.sourceforge.net/project/pcre/pcre/8.38/pcre-8.38.tar.bz2
$ tar -xjvf pcre-8.38.tar.bz2
$ nginx-build -d . -clear --with-pcre=$(pwd)/pcre-8.38
$ mkdir logs conf
$ cp nginx/1.9.15/nginx-1.9.15/conf/mime.types ./conf
$ cat <<EOF > conf/nginx.conf
worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include mime.types;

    upstream app {
        server localhost:3000;
    }

    server {
        listen 8000;
        server_name localhost;
        root html;

        location / {
            try_files $uri $uri/index.html $uri.html @app;
        }

        location @app {
            proxy_pass http://app;
        }
    }
}
EOF
$ mkdir html
$ echo html > html/index.html
$ ./nginx/1.9.15/nginx-1.9.15/objs/nginx -p $(pwd) -c conf/nginx.conf
$ curl http://localhost:8000/index.html
html
$ curl http://localhost:8000/app
GET
$ curl -X POST http://localhost:8000/app
POST

Basic 認証を設定する

limit_except の前に、リクエストメソッドにかかわらず全てに対して Basic 認証をかけてみる。

$ cp conf/nginx.conf conf/nginx.conf.orig
$ vi conf/nginx.conf
$ diff -u conf/nginx.conf.orig conf/nginx.conf
--- conf/nginx.conf.orig    2016-04-23 16:31:35.000000000 +0900
+++ conf/nginx.conf 2016-04-23 16:48:22.000000000 +0900
@@ -18,6 +18,8 @@

         location / {
             try_files $uri $uri/index.html $uri.html @app;
+            auth_basic "Basic auth";
+            auth_basic_user_file .htpasswd;
         }

         location @app {
$ echo "user:$(openssl passwd -apr1 password)" > conf/.htpasswd
$ ./nginx/1.9.15/nginx-1.9.15/objs/nginx -p $(pwd) -c conf/nginx.conf -s reload
$ curl -u 'user:password' http://localhost:8000/app
GET
$ curl -X POST -u 'user:password' http://localhost:8000/app
POST

limit_except を使って POST リクエストにのみ Basic 認証

POST メソッドでのリクエストの時のみ、Basic 認証を要求する。

$ vi conf/nginx.conf
$ diff -u conf/nginx.conf.orig conf/nginx.conf
--- conf/nginx.conf.orig    2016-04-23 16:31:35.000000000 +0900
+++ conf/nginx.conf 2016-04-23 16:51:08.000000000 +0900
@@ -18,6 +18,10 @@

         location / {
             try_files $uri $uri/index.html $uri.html @app;
+            limit_except GET {
+                auth_basic "Basic auth";
+                auth_basic_user_file .htpasswd;
+            }
         }

         location @app {
$ ./nginx/1.9.15/nginx-1.9.15/objs/nginx -p $(pwd) -c conf/nginx.conf -s reload
$ curl http://localhost:8000/app
GET
$ curl -i -X POST -u 'user:password' http://localhost:8000/app
HTTP/1.1 404 Not Found
Server: nginx/1.9.15
Date: Sat, 23 Apr 2016 07:51:33 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive

<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.9.15</center>
</body>
</html>

404 Not Found

なぜ?

ちなみに、Basic 認証とか関係なく limit_except ディレクティブを使った時点で 404 Not Found になってしまう。

$ vi conf/nginx.conf
$ diff -u conf/nginx.conf.orig conf/nginx.conf
--- conf/nginx.conf.orig    2016-04-23 16:31:35.000000000 +0900
+++ conf/nginx.conf 2016-04-23 16:54:31.000000000 +0900
@@ -18,6 +18,8 @@

         location / {
             try_files $uri $uri/index.html $uri.html @app;
+            limit_except GET {
+            }
         }

         location @app {
$ ./nginx/1.9.15/nginx-1.9.15/objs/nginx -p $(pwd) -c conf/nginx.conf -s reload
$ curl http://localhost:8000/app
GET
$ curl -i -X POST -u 'user:password' http://localhost:8000/app
HTTP/1.1 404 Not Found
Server: nginx/1.9.15
Date: Sat, 23 Apr 2016 07:51:33 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive

<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.9.15</center>
</body>
</html>

limit_except を別の location に移す

try_files の内部リダイレクト先の location ディレクティブの方で limit_except ディレクティブを使えば 404 Not Found にはならない。

$ vi conf/nginx.conf
$ diff -u conf/nginx.conf.orig conf/nginx.conf
--- conf/nginx.conf.orig    2016-04-23 16:31:35.000000000 +0900
+++ conf/nginx.conf 2016-04-23 16:58:00.000000000 +0900
@@ -21,6 +21,10 @@
         }

         location @app {
+            limit_except GET {
+                auth_basic "Basic auth";
+                auth_basic_user_file .htpasswd;
+            }
             proxy_pass http://app;
         }
     }
$ ./nginx/1.9.15/nginx-1.9.15/objs/nginx -p $(pwd) -c conf/nginx.conf -s reload
$ curl http://localhost:8000/app
GET
$ curl -X POST -u 'user:password' http://localhost:8000/app
POST

まとめ

そういうものなのかな?
ドキュメントの探し方が悪いのか、該当する説明は見つけられませんでした。
ソースを読めば分かるのかも知れませんが、めんどくさくなってきたので、泥臭いけど動く方法でごまかそうと思ってます。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2