Ray Lee | 李宗叡
Learn or Die
Published in
5 min readApr 22, 2024

--

# 前言

紀錄 Nginx config 的細節 route 流程

# config

以下為簡化後的 Laravel document 的預設 Nginx config

server {
listen 80;
listen [::]:80;
server_name example.com;
root /srv/example.com/public;

index index.php;

location / {
try_files $uri $uri/ /index.php?$query_string;
}

location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }

error_page 404 /index.php;

location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
}

location ~ /\.(?!well-known).* {
deny all;
}
}

# 初步語法解析

  • listen:監聽的 port
  • server_name:request host name
  • root:location 會到哪一個位置 search file,如上範例,會到 /src/example.com/public 下,套用 location 規則搜尋
  • index:當 destination 為 dir 時,會嘗試在 dir 底下搜尋 index.php file
  • location / {}:match 所有 url
  • location = /favicon.ico:當 $url === /favicon.ico 時,才會執行 { } 內的 code
  • access_log off:該筆 request 不會 log 到 access_log
  • error_page 404:若 fastcgi 返回 404 時,則觸發此 block,不過唯有當 fastcgi_intercept_errors on; 時這個 config 才有作用。若是使用 proxy pass 的話則是 proxy_intercept_errors on;。所以可以理解為,這個 config 基本上是無作用的
  • location ~:正則搜尋,為 case sensitive
  • location ~ .php$:符合 .php 結尾的會進到該 location
  • fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;:將 request pass 到指定 unix process socket
  • include fastcgi_params;:include common params,檔案通常會放在 /etc/nginx 底下
  • fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;:assign $realpath_root$fastcgi_script_name into 名為 SCRIPT_FILENAME 的 fastcgi_param,若該 fastcgi_param 已存在於 fastcgi_params file,則按讀取順序覆蓋,所以 include common params 務必置於自定義 param 上方
  • location ~ /.(?!well-known).* { … }:如果 $uri 的 pattern 為 /.(xxx) 開頭,只要不符合 /.well-known pattern 的全部 deny,.well-known 的用途在於驗證 SSL 憑證時會將 challenge file 放在此 dir 下

# 流程解析

當 request uri 為 example.com/app.css 時,會依照 location rule 來 search

  • 依照 location rule,符合 / location block
  • /srv/example.com/public 下尋找 app.css
  • 沒找到,尋找 /srv/example.com/public/app.css/ dir 是否存在
  • 若存在,則依據 index 語法設定,尋找 index.php 是否存在
  • 若不存在,則 rewrite request uri 為 /index.php?$query_string;
  • 依照 location rule,先經由前綴原則找到 / location block
  • 依照 location rule,使用正則尋找符合的 location block,找到 ~ \.index.php$ location block
  • 設定 fastcgi params 為 fastcgi_params file 定義的 params 以家 SCRIPT_FILENAME 為 $realpath_root$fastcgi_script_name,即 /src/example.com/public/index.php
  • 將 request pass 到 fastcgi process socket

# 流程圖

可先參考 location rule,或參考 location rule 的簡易流程圖

然後是 try_files 的流程圖

# 參考資料

--

--

Ray Lee | 李宗叡
Learn or Die

It's Ray. I do both backend and frontend, but more focus on backend. I like coding, and would like to see the whole picture of a product.