Nginx location 比對順序 --- 不要再有 bug!



前言

  • 在寫 nginx location 時,偶而會發現 match 結果不如預期,因為對它判斷順序不夠熟悉。

  • 本文簡記他判斷的順序。




說明

語法註記

=:exactly,完全符合才會 match

1
location = /path

^~ :forward match (或 priority prefix),前綴符合才會 match

1
location ^~ /path

~:regex - case sensitive,區分大小寫的正規表達式

1
location ~ /path

~*:regex - case insensitive,不區分大小寫的正規表達式

1
location ~* .(jpg|png)

/:一般 match

1
location /path

範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
location  = / {
    # matches the query / only.
    
    ### [ configuration A ]  ###
    
}
location  / {
    # matches any query, since all queries begin with /, but regular
    # expressions and any longer conventional blocks will be
    # matched first.
    
    ### [ configuration B ]  ###
    
}
location /documents/ {
    # matches any query beginning with /documents/ and continues searching,
    # so regular expressions will be checked. This will be matched only if
    # regular expressions don't find a match.
    
    ### [ configuration C ]  ###
    
}
location ^~ /images/ {
    # matches any query beginning with /images/ and halts searching,
    # so regular expressions will not be checked.
    
    ### [ configuration D ]  ###
    
}
location ~* \.(gif|jpg|jpeg)$ {
    # matches any request ending in gif, jpg, or jpeg. However, all
    # requests to the /images/ directory will be handled by
    # Configuration D.   
    
    ### [ configuration E ]  ###
    
}

比較表

Case location 語法 說明 會繼續往下判斷 Regex
A = / 只會 match 單一一個 / False
B / match 全部;但是 regex 以及更長的名字會優先 True
C /documents/ 就算 match 還是會繼續找 regex,如果沒有沒有符合 regex 才會套用這個 True
D ^~ /images/ match /images/ 開頭的結果、且不會繼續搜尋其他可能 False
E ~* \.(gif|jpg|jpeg)$ match 這些檔名結尾的結果;但如果有先 match Case D,則不會 match 這個

更多範例

假設以下 config

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
    server {
      listen 80;
      server_name example.com;
    
      location = / {
      }
    
      location / {
      }
    
      location /example/ {
      }
    
      location ^~ /example/important {
      }
    
      location ~* \.(ex1|ex2|ex3)$ {
      }
    }

這五個 location 分成 A, B, C, D, E,各自的 match 說明如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
    A:
      Location: /
      Match type: exact
    
    B:
      Location: /
      Match type: prefix
    
    C:
      Location: /example/
      Match type: prefix
    
    D:
      Location: /example/important 
      Match type: forward match (或 priority prefix)
    
    E:
      Location: \.(ex1|ex2|ex3)$
      Match type: case insensitive regex

收到的 request,以及其對應 match 的 location 會如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
    / : A
    
    /test/path : B
    
    /example/page : C
    
    /example/important : D
    
    /file.ex1 : E
    
    /example_a/my/resources : B
    
    /example_a : B
    
    /test/.ex2 : E
    
    /example/page/extra : C
    
    /example/important/data : D
    
    /file.ex4 : B
    
    /default : B
    
    /example_a/some/file.ex2 : E
    
    /some/random/path : B
    
    /test/ex1 : E
    
    /example/important/file : D
    
    /file.EX2 : E
    
    /example_a/important/file : B
    
    /example/some/file.ex3 : E
    
    /example/important/extra/file.ex2 : D



REF

Licensed under CC BY-NC-SA 4.0
最後更新 2024-05-24 14:47

主題 StackJimmy 設計