domo

domo

nginxのパスのマッチングの問題

前書き#

nginx とのやり取りは多く、よく 404 の問題に遭遇します。毎回結果を書くために情報を調べる必要があります。今回はまとめてみます。

問題#

アクセスするドメインは localhost/store/add_order.html です。
ウェブのルートディレクトリは /www/web です。
store はサブディレクトリです。

解決策#

以下のように設定します。
デフォルトのパス(Mac)

/usr/local/etc/nginx/nginx.conf
server {
    listen       80;
    server_name  localhost;
    root   /www/web;
    #charset koi8-r;
    location / {
        index  index.php index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        fastcgi_pass   php:9000;
        fastcgi_index  index.php;
        include        fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    }

    location ^~ /api/ { 
        proxy_pass http://www.api.com/; 
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

上記の location には 3 つのマッチルールが存在します。

最初にマッチするのは location = /50x.html です。
次にマッチするのは location ~ .php$ です。
最後にマッチするのは / です。

例えば、http://localhost/store/add-order.html では、/www/web ディレクトリ内の store/add-order.html ファイルを探します。

例えば、http://localhost/store/add-order.php では、/www/web ディレクトリと store/add-order.php を組み合わせて SCRIPT_FILENAME に渡し、PHP コンポーネントに渡します。

代理#

例えば、http://localhost/api/add-order.php の場合、http://www.api.com/add-order.php に代理されます。

ただし、末尾に / がない場合は、

proxy_pass http://www.api.com;

となり、http://www.api.com/api/add-order.php に代理されます。

追加情報#

location は URL にマッチするために使用されます。
これは曖昧なマッチングを行います。
/ がない場合、location /abc/def は /abc/defghi リクエストや /abc/def/ghi などにマッチします。
/ がある場合、location /abc/def/ は /abc/defghi リクエストにマッチせず、/abc/def/anything などにのみマッチします。

拡張#

location = / {
   #ルールA
}
location = /login {
   #ルールB
}
location ^~ /static/ {
   #ルールC
}
location ~ \.(gif|jpg|png|js|css)$ {
   #ルールD、注意:括弧内の大文字小文字を区別してマッチングします。括弧内はすべて小文字で、小文字のみにマッチします。
}
location ~* \.png$ {
   #ルールE
}
location !~ \.xhtml$ {
   #ルールF
}
location !~* \.xhtml$ {
   #ルールG
}
location / {
   #ルールH
}

これによって次のような効果が生じます:

ルートディレクトリ / にアクセスする場合、例:http://localhost/ はルール A にマッチします。

http://localhost/login にアクセスすると、ルール B にマッチします。http://localhost/register はルール H にマッチします。

http://localhost/static/a.html にアクセスすると、ルール C にマッチします。

http://localhost/a.gif、http://localhost/b.jpg はルール D とルール E にマッチしますが、ルール D が優先され、ルール E は適用されません。一方、http://localhost/static/c.png はルール C に優先的にマッチします。

http://localhost/a.PNG にアクセスすると、ルール E にマッチしますが、ルール D にはマッチしません。ルール E は大文字小文字を区別しません。

http://localhost/a.xhtml にアクセスすると、ルール F とルール G にはマッチしません。

http://localhost/a.XHTML にはルール G にはマッチしません(! のため)。ルール F とルール G は除外法であり、マッチするルールにもマッチしません。実際のアプリケーションでどこで使用されるか考えてみてください。

http://localhost/category/id/1111 にアクセスすると、最終的にルール H にマッチします。なぜなら、上記のルールにはマッチせず、この時点で nginx はバックエンドのアプリケーションサーバー(例:FastCGI(php)、tomcat(jsp))にリクエストを転送する逆方向プロキシサーバーとして存在するからです。

優先度:(location =) > (location 完全パス ) > (location ^~ パス) > (location ~,~* 上から下への正規表現の順序、最後の一致) > (location 部分開始パス) > (/)

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。