

mediawikiをインストール、ショートURLのためにnginxを設定中。

<https://www.mediawiki.org/wiki/Manual:Short_URL/Nginx/ja>  
公式のサンプルコード（Manual:Short URL/Nginx/ja）を元に  
/etc/nginx/conf.d/mediawiki.confに以下のような設定。

[code]

    server {
        server_name example.com;
        root /home/taro/mediawiki;
    
        # Location for wiki's entry points
        location ~ ^/(index|load|api|thumb|opensearch_desc|rest|img_auth)\.php$ {
            include /etc/nginx/fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_pass 127.0.0.1:9000;
        }
        
        # Images
        location /w/images {
            # Separate location for images/ so .php execution won't apply
        }
        location /w/images/deleted {
            # Deny access to deleted images folder
            deny all;
        }
        # MediaWiki assets (usually images)
        location ~ ^/w/resources/(assets|lib|src) {
            try_files $uri 404;
            add_header Cache-Control "public";
            expires 7d;
        }
        # Assets, scripts and styles from skins and extensions
        location ~ ^/w/(skins|extensions)/.+\.(css|js|gif|jpg|jpeg|png|svg|wasm)$ {
            try_files $uri 404;
            add_header Cache-Control "public";
            expires 7d;
        }
        # Favicon
        location = /favicon.ico {
            alias /w/images/6/64/Favicon.ico;
            add_header Cache-Control "public";
            expires 7d;
        }
    
        # License and credits files
        location ~ ^/w/(COPYING|CREDITS) {
            default_type text/plain;
        }
    
        
        # Handling for Mediawiki REST API, see [[mw:API:REST_API]]
        location /w/rest.php/ {
            try_files $uri $uri/ /w/rest.php?$query_string;
        }
    
        ## Uncomment the following code for handling image authentication
        ## Also add "deny all;" in the location for /w/images above
        #location /w/img_auth.php/ {
        #   try_files $uri $uri/ /w/img_auth.php?$query_string;
        #}
    
        # Handling for the article path (pretty URLs)
        location /wiki/ {
            rewrite .* /index.php;
        }
    
        # Allow robots.txt in case you have one
        location = /robots.txt {
        }
        # Explicit access to the root website, redirect to main page (adapt as needed)
        location = / {
            return 301 /wiki/メインページ;
        }
    
        # Every other entry point will be disallowed.
        # Add specific rules for other entry points/images as needed above this
        location / {
            return 404;
        }
    }
    
[/code]

ブラウザで  
`http://example.com`  
にアクセスすると  
`http://example.com/wiki/メインページ`  
へリダイレクトされる。

`http://example.com/index.php?title=メインページ`  
へアクセスしても全く同じページが表示される。

mediawiki.confの設定を解読中なのですが、なぜそういう動きになるのか理解できず。  
多段階で内部リダイレクトが発生していると思うのですが、自分の理解とnginxの動きが一致しているのか確認するため、どのlocationディレクティブが適用されているのかを知りたいです。

現状の自分の理解は以下の通りです。

ブラウザで  
`http://example.com`  
にアクセスすると

[code]

      # Explicit access to the root website, redirect to main page (adapt as needed)
        location = / {
            return 301 /wiki/メインページ;
        }
    
[/code]

が適用され  
`http://example.com/wiki/メインページ`  
にリダイレクトされる。  
（ブラウザ上でのURLも`http://example.com/wiki/メインページ`になる）

さらに

[code]

        # Handling for the article path (pretty URLs)
        location /wiki/ {
            rewrite .* /index.php;
        }
    
[/code]

が適用され  
`http://example.com/index.php`  
に内部リダイレクトされる。  
（`/メインページ`という情報が消えてしまう？）

ブラウザ上での表示は`http://example.com/wiki/メインページ`のまま。

さらに

[code]

        # Location for wiki's entry points
        location ~ ^/(index|load|api|thumb|opensearch_desc|rest|img_auth)\.php$ {
            include /etc/nginx/fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_pass 127.0.0.1:9000; # or whatever port your PHP-FPM listens on
        }
    
[/code]

が適用され  
`/home/taro/mediawiki/index.php`  
がcgiで実行される。  
（`/メインページ`という情報はどうなった？）

以下の2つのURLで同じページが表示されるので  
`http://example.com/wiki/メインページ`  
`http://example.com/index.php?title=メインページ`

`/wiki/メインページ`というパスが  
`?title=メインページ`というクエリに変換されて  
`/home/taro/mediawiki/index.php`に引き渡されているのだと思うのですが、なぜそうなるのか分かりません。

[code]

        # Handling for the article path (pretty URLs)
        location /wiki/ {
            rewrite .* /index.php;
        }
    
[/code]

を経由すると`/メインページ`の情報が消えてしまうように感じるので、  
そもそもこのlocationディレクティブを経由しているという認識が間違っているのかも？

ということで、nginxの内部リダイレクトでどのlocationディレクティブがどういう順序で適用されているのかを正確にトレースしたいです。

nginxの.confの中にprintf()だとかconsole.log()だとか、echoだとかを書いて、ログにメッセージを残すみたいなことはできないのでしょうか？

`/var/log/nginx/access.log`  
を確認したところ  
`/wiki/メインページ`  
へのアクセスのみが記録されているように思います。  
（細かいログが他にも記録されているが、おそらくcssや画像などのロードが記録されているだけ）


CC BY-SA 4.0
2021-06-16T00:38:57.457
77588
2021-06-17T01:42:58.927
45540
question
php 正規表現 nginx url cgi
nginx、どのlocationディレクティブが適用されたかデバッグするには？


> `/wiki/メインページ` というパスが `?title=メインページ` というクエリに変換されて
> `/home/taro/mediawiki/index.php` に引き渡されているのだと思うのですが、なぜそうなるのか分かりません。

実は `REQUEST_URI` から自動的に `PATH_INFO` に相当する部分(`メインページ`) を取り出しているのです。

[リリースノート/1.20 -
MediaWiki](https://www.mediawiki.org/wiki/Release_notes/1.20/ja#MediaWiki_1.20.0)

**Configuration changes**

> `$wgUsePathInfo = true;` is no longer needed to make `$wgArticlePath` work
> on servers using like nginx, lighttpd, and apache over fastcgi. **MediaWiki
> now always extracts path info from REQUEST_URI** if it's available.

前回の質問に対する回答で言及した古い `nginx.conf` から `PATH_INFO` の設定が削除されていたのはこのためなのではないかと思います。

[https://www.mediawiki.org/w/index.php?title=Manual:Short_URL/Nginx&oldid=3103792](https://www.mediawiki.org/w/index.php?title=Manual:Short_URL/Nginx&oldid=3103792)

[code]

    location /wiki/ {
        rewrite ^/wiki/(?<pagename>.*)$ /w/index.php;
        include /etc/nginx/fastcgi_params;
        # article path should always be passed to index.php
        fastcgi_param SCRIPT_FILENAME $document_root/w/index.php;
        fastcgi_param PATH_INFO $pagename;
        fastcgi_param QUERY_STRING $query_string;
        fastcgi_pass 127.0.0.1:9000; # or whatever port your PHP-FPM listens on
    }
    
[/code]


CC BY-SA 4.0
2021-06-16T03:01:21.647
77591
2021-06-16T03:01:21.647
77588
answer


以下の3つのlocationディレクティブ、1つずつコメントアウトして実験しました。

[code]

    # Explicit access to the root website, redirect to main page (adapt as needed)
    location = / {
      return 301 /wiki/メインページ;
    }
    
[/code]

[code]

    # Handling for the article path (pretty URLs)
    location /wiki/ {
      rewrite .* /index.php;
    }
    
[/code]

[code]

    # Location for wiki's entry points
    location ~ ^/(index|load|api|thumb|opensearch_desc|rest|img_auth)\.php$ {
      include /etc/nginx/fastcgi_params;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_pass 127.0.0.1:9000; # or whatever port your PHP-FPM listens on
    }
    
[/code]

`location = /`だけをコメントアウトした場合。

`http://example.com`にアクセスるすると404 Not Found。  
`http://example.com/wiki/メインページ`へのリダイレクトが発生しない。

`http://example.com/wiki/メインページ`に直接アクセスするとメインページが正常に表示される。  
`http://example.com/index.php?title=メインページ`に直接アクセスするとメインページが正常に表示される。

* * *

`location /wiki/`だけをコメントアウトした場合。

`http://example.com`は  
`http://example.com/wiki/メインページ`へリダイレクトされた後、404 Not Found。

`http://example.com/wiki/メインページ`に直接アクセスした場合も404 Not Found。

`http://example.com/index.php?title=メインページ`はページが表示される。

* * *

`location ~
^/(index|load|api|thumb|opensearch_desc|rest|img_auth)\.php$`だけをコメントアウトした場合。

`http://example.com`  
`http://example.com/wiki/メインページ`  
`http://example.com/index.php?title=メインページ`  
3つのURLですべて404 Not Found。

* * *

locationディレクティブの適用順序は、

  1. `location = /`
  2. `location /wiki/`
  3. `location ~ ^/(index|load|api|thumb|opensearch_desc|rest|img_auth)\.php$`

の順序で間違いなさそう。  
（段階的に404 Not FoundになるURLが増えるから）

コメントアウトしながら現象を観測する以外に、  
どのディレクティブがどの順序で適用されたかを明確に把握する方法をご存知の方がいたら情報ください。

* * *

リダイレクトされるURLは、

`http://example.com`  
↓ 外部リダイレクト  
`http://example.com/wiki/メインページ`  
↓ 内部リダイレクト  
`http://example.com/index.php?title=メインページ`

という動きだと思っていたけど、

`http://example.com`  
↓ 外部リダイレクト  
`http://example.com/wiki/メインページ`  
↓ 内部リダイレクト  
`http://example.com/index.php`

という動きをしているっぽい。

`REQUEST_URI`に`/wiki/メインページ`というテキストがセットされて、`index.php`の中で利用されているっぽい。  
`index.php`のソース中には`$_SERVER['REQUEST_URI']`は使われていないが、`index.php`で`require`しているファイルの中のどれかで使っていると思われる。

最終的に  
`http://example.com/index.php`に内部リダイレクトされるとしたら、  
`REQUEST_URI`の値は`/index.php`になるんじゃないの？  
なぜ中間の`/wiki/メインページ`が採用されるの？

多段的にリダイレクトされた場合、REQUEST_URIがどのように決定されるのか、誰か教えてください。  
たぶん、外部リダイレクトと内部リダイレクトの違いだと思うけど、自力ではドキュメントを見つけられず。


CC BY-SA 4.0
2021-06-16T13:39:11.590
77599
2021-06-16T13:39:11.590
45540
77588
answer


nginxに任意のログメッセージを出力する方法。

`/etc/nginx/nginx.conf`  
に以下の1行を追加。

`log_format mydebug "[MYDEBUG][$time_local] $request_uri, dbg1:$dbg1
dbg2:$dbg2 dbg3:$dbg3";`

（mydebug や $dbg1 は任意の文字列）

`/etc/nginx/conf.d/mediawiki.conf`  
に下記の3か所で`set ～～`と`access_log ～～`を追加.

[code]

    # Location for wiki's entry points
    location ~ ^/(index|load|api|thumb|opensearch_desc|rest|img_auth)\.php$ {
    
      set $dbg1 $msec;
      access_log /var/log/nginx/mydebug.log mydebug;
    
      include /etc/nginx/fastcgi_params;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_pass 127.0.0.1:9000; # or whatever port your PHP-FPM listens on
    }
    
[/code]

[code]

    # Handling for the article path (pretty URLs)
    location /wiki/ {
    
      set $dbg2 $msec;
      access_log /var/log/nginx/mydebug.log mydebug;
    
      rewrite .* /index.php;
    }
    
[/code]

[code]

    # Explicit access to the root website, redirect to main page (adapt as needed)
    location = / {
    
      set $dbg3 $msec;
      access_log /var/log/nginx/mydebug.log mydebug;
    
      return 301 /wiki/メインページ;
    }
    
[/code]

`mydebug.log`を確認すると以下のようなログが確認できる。

> [MYDEBUG][17/Jun/2021:09:51:09 +0900] /, dbg1: dbg2: dbg3:1623891069.090  
>  [MYDEBUG][17/Jun/2021:09:51:09 +0900]
> /wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8,
> dbg1:1623891069.100 dbg2:1623891069.100 dbg3:

`$request_uri`が`/`、  
`dbg3`にタイムスタンプが入ったログがまず記録される。

`location = /`のディレクティブが最初に適用されていることが確定。

`$request_uri`が`/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8`（/wiki/メインページ）,
`dbg1`と`dbg2`にタイムスタンプが入ったログが次に記録される。

`dbg1`と`dbg2`のタイムスタンプは同じ値。  
`dbg1`と`dbg2`どちらが先かは分からないが、連続して処理されているっぽい。

ログが3行分記録されることを期待していたが、2行しかない。

`dbg2`の方の`access_log ～～`はコメントアウトしても、ログの出力に影響なし。  
`dbg1`側の`access_log ～～`だけ採用されて、`dbg2`側の`access_log ～～`は使われていないみたい。

`rewrite`（内部リダイレクト）の場合、最終的にたどりついたlocationディレクティブで`access_log`が記録されると思われる。

* * *

REQUEST_URIの話。

`http://example.com`  
↓  
`http://example.com/wiki/メインページ`  
↓  
`http://example.com/index.php`

という1連の処理だと認識していたのが間違い。

ブラウザ： `http://example.com`へリクエスト  
サーバー： `http://example.com/wiki/メインページ`の方へアクセスしてくださいというレスポンス。

ここで1つ目のリクエストは終了。

ブラウザ： `http://example.com/wiki/メインページ`へリクエスト  
サーバー： なんやかんや処理してhtmlをレスポンス。

2つ目のリクエストでは、`http://example.com/wiki/メインページ`へアクセスしているので、`REQUEST_URI`は`/wiki/メインページ`になる。


CC BY-SA 4.0
2021-06-17T01:42:58.927
77614
2021-06-17T01:42:58.927
45540
77588
answer