やりたいこと
複数のアプリケーションを、同一の virtualhost 内で動かす。
http://example.com/app1/hello にアクセスすると、 localhost の uwsgi で動いているアプリの /hello に飛ばすとか。
基礎知識
(多分CGI由来の) 3つの重要な変数を理解しましょう。
REQUEST_URI: /app/hello
SCRIPT_NAME: /app
PATH_INFO: /hello
REQUEST_URI が、ユーザーがアクセスしたホスト名以降のパスです。
SCRIPT_NAME が、アプリが動いている場所です。 CGI だったら .cgi
とか php だったら .php
とか拡張子があったりします。
PATH_INFO が、 SCRIPT_NAME 以降のパスです。アプリのURLディスパッチャはこの変数を見たりします。
この3つの変数がきちんと設定できていないと、URLディスパッチやリダイレクトが上手く動かない事になります。
nginx + uwsgi
デフォルトで用意されている、 include するだけで使える uwsgi_params で、
uwsgi_param REQUEST_URI $request_uri
と書かれているのは、そのまま変更する必要がありません。 PATH_INFO
は $document_uri
に設定されているのですが、これを適切に上書きしてやる必要があります。
SCRIPT_NAME と PATH_INFO の設定を、 nginx 側でやる方法と、 uwsgi 側でやる方法があります。
nginx 側で設定する
このやり方は uwsgi だけじゃなくて http や fastcgi など他のリバースプロキシ方法でアプリケーションを動かすときにも応用できるのでお勧めです。
location ~ ^/app/(.*)$ {
uwsgi_pass unix:/var/run/uwsgi/app.sock;
include /usr/local/nginx/conf/uwsgi_params;
uwsgi_param SCRIPT_NAME /app;
uwsgi_param PATH_INFO /$1;
}
uwsgi 側で設定する
uwsgi の mount を使ってアプリケーションの prefix を設定している場合、 manage-script-name
オプションを使って SCRIPT_NAME と PATH_INFO を設定することもできます。
アプリ本体とヘルスチェック用の wsgi スクリプトを別に用意しているなどで、 mount を使っている場合はこちらの方法が便利です。
location ~ ^/app/(.*)$ {
uwsgi_pass unix:/var/run/uwsgi/app.sock;
include /usr/local/nginx/conf/uwsgi_params;
}
[uwsgi]
master = true
lazy-apps = true
socket = /var/run/uwsgi/app.sock
workers = 4
mount = /app=wsgi.py
manage-script-name = true