Help us understand the problem. What is going on with this article?

nginx $document_root$fastcgi_script_name と $request_filename の違い

More than 3 years have passed since last update.

前書き

ファイルが存在するかどうかの記述でよく、 if (-f $request_filename) { ... }if (-f $document_root$fastcgi_script_name) { ... } の2通りがあるが、これって何か違うの?って思った時がありました。

その頃、調べた内容を下記に記します。

変数の意味

$request_filename

Module ngx_http_core_module #variables

現在のリクエストのファイルパスは、 root または alias ディレクティブとリクエストの URI に基づきます。

$document_root

Module ngx_http_core_module #variables

現在のリクエストの root または alias ディレクティブの値です。

$fastcgi_script_name

Module ngx_http_fastcgi_module #variables

URI がスラッシュで終わっている場合、URI をリクエストするか、 URI に fastcgi_index ディレクティブによって設定されたインデックスファイル名をつけてリクエストしてください。この変数は、 PHPのスクリプト名を決定する SCRIPT_FILENAMEPATH_TRANSLATED パラメータを設定するために使用することができます。例えば、次のディレクティブを持つ /info/ リクエストについて

fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;

SCRIPT_FILENAME パラメータは /home/www/scripts/php/info/index.php と等しい。
fastcgi_split_path_info ディレイクティブを使っている場合、 $fastcgi_script_name はそのディレイクティブにより設定された一つ目のキャプチャの値と等しい。

※ 正規表現では、特定のパターンにマッチした文字列を後で参照できるように保存しておくことをキャプチャと呼びます。

上記の変数を扱う上で押さえておくべき重要なディレイクティブ

fastcgi_split_path_info ディレイクティブ

Module ngx_http_fastcgi_module #fastcgi_split_path_info

Syntax:   fastcgi_split_path_info regex;
Default:  —
Context:  location

$fastcgi_path_info の値をキャプチャする正規表現を定義します。正規表現は、2つのキャプチャを持つ必要があります。一つ目は $fastcgi_script_name の値になり、二つ目は $fastcgi_path_info の値になります。例えば、以下のようなの設定の場合

location ~ ^(.+\.php)(.*)$ {
    fastcgi_split_path_info       ^(.+\.php)(.*)$;
    fastcgi_param SCRIPT_FILENAME /path/to/php$fastcgi_script_name;
    fastcgi_param PATH_INFO       $fastcgi_path_info;

そして、 /show.php/article/0001 リクエストは、SCRIPT_FILENAME パラメータは /path/to/php/show.php と等しく、 PATH_INFO パラメータは /article/0001 と等しい。

fastcgi_index ディレイクティブ

Module ngx_http_fastcgi_module #fastcgi_index

Syntax:   fastcgi_index name;
Default:  —
Context:  http, server, location

$fastcgi_script_name の値で、スラッシュで終わる URI の後に追加されるファイル名を設定します。例えば、以下のような設定の場合

fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;

そして、 /page.php リクエストは、SCRIPT_FILENAME パラメータは /home/www/scripts/php/page.php と等しく、 / とリクエストされた場合は /home/www/scripts/php/index.php と等しい。

本題

結局違いは?

下記の記事を見つけました。

web server - Nginx $document_root$fastcgi_script_name vs $request_filename - Server Fault

You get the request "/info/" and have the following configuration:

fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;

SCRIPT_FILENAME would equal "/home/www/scripts/php/info/index.php", but using $request_filename it would just be "/home/www/scripts/php/info/".

/info/ とリクエストされ、 SCRIPT_FILENAME パラメータに /home/www/scripts/php$fastcgi_script_name を使用した場合 /home/www/scripts/php/info/index.php と等しいが、 $request_filename を使用した場合は /home/www/scripts/php/info/ と等しい。

とのことでした。上記の記述が正しいかどうか実証してみます。

実証

前提

下記の記事内容を最低限把握している程で実証をするため、インストール手順や公開ディレクトリの作成、設定後の再起動等は省略します。

nginx と php-fpm の仕組みをちゃんと理解しながら PHP の実行環境を構築する - Qiita

環境

/etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.1 LTS"

設定

add_header ディレイクティブを使って変数の確認を行います。詳しく知りたい方は下記をご覧ください。

nginx 変数の値を確認したい時は add_header ディレイクティブを使うと超絶簡単 - Qiita

/etc/nginx/nginx.conf
server {
    listen 80 default_server;

    root /home/www/scripts/php;
    index index.php index.html index.htm;

    server_name localhost;

    location /info/ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;

        add_header $request_filename $request_filename;
        add_header $document_root$fastcgi_script_name $document_root$fastcgi_script_name;
    }
}

変数の値を確認

/info/ でリクエスト
$ curl -I localhost/info/
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Mon, 28 Mar 2016 11:30:28 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
$request_filename: /var/www/info/
$document_root$fastcgi_script_name: /var/www/info/index.php
/info/index.php でリクエスト
$ curl -I localhost/info/index.php
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Mon, 28 Mar 2016 11:30:13 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
$request_filename: /var/www/info/index.php
$document_root$fastcgi_script_name: /var/www/info/index.php

参考文献

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした