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