# 【Nginx】location 匹配規則

### 一般匹配

location \[=|~|~\*|^~\] /uri/ { ... }

<table id="bkmrk-%E6%A8%A1%E5%BC%8F-%E5%90%AB%E4%B9%89-location-%3D-%2Fur"><thead><tr><th>模式</th><th>含义</th></tr></thead><tbody><tr><td>location = /uri</td><td>= 表示精确匹配，只有完全匹配上才能生效</td></tr><tr><td>location ^~ /uri</td><td>^~ 开头对URL路径进行前缀匹配，并且在正则之前。</td></tr><tr><td>location ~ pattern</td><td>开头表示区分大小写的正则匹配</td></tr><tr><td>location ~\* pattern</td><td>开头表示不区分大小写的正则匹配</td></tr><tr><td>location /uri</td><td>不带任何修饰符，也表示前缀匹配，但是在正则匹配之后</td></tr><tr><td>location /</td><td>通用匹配，任何未匹配到其它location的请求都会匹配到，相当于switch中的default</td></tr></tbody></table>

<div id="bkmrk-"></div>實際使用規則至少有三個匹配定義

```Nginx
# 直接匹配网站根，通过域名访问网站首页比较频繁，使用这个会加速处理，官网如是说。 # 这里是直接转发给后端应用服务器了，也可以是一个静态首页
# 第一个必选规则
location = / {
    proxy_pass http://tomcat:8080/index
}
# 第二个必选规则是处理静态文件请求，这是 nginx 作为 http 服务器的强项
# 有两种配置模式，目录匹配或后缀匹配，任选其一或搭配使用 
location ^~ /static/ {
    root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
    root /webroot/res/;
}
# 第三个规则就是通用规则，用来转发动态请求到后端应用服务器
# 非静态文件请求就默认是动态请求，自己根据实际把握
# 毕竟目前的一些框架的流行，带.php、.jsp后缀的情况很少了 location / {
    proxy_pass http://tomcat:8080/
}
```

依據檔案類型設置過期時間

```Nginx
location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ {
    if (-f $request_filename) {
expires 1h;
break; }
}
```

禁止訪問某目錄

```Nginx
location ~* \.(txt|doc)${
    root /data/www/wwwroot/linuxtone/test;
    deny all;
}
```

---

### 內部命名位置

#### 命名位置的用途

- **`@` 開頭**: 這個符號用來表示這是一個內部使用的命名位置，不會與普通 URL 路徑混淆。
- **命名自由**: 你可以給命名位置起任何名稱，只要以 `@` 開頭並且不與其他位置塊或指令名稱衝突。

#### 如何使用命名位置

命名位置常用於內部重定向，當某些條件滿足時會跳轉到這些位置。通常用在 `try_files`、`error_page` 等指令中。

#### 命名位置的典型應用

- **靜態資源**: 先查找靜態文件，如果找不到則交給動態處理程序處理。
- **錯誤處理**: 如果遇到特定錯誤碼，重定向到特定的錯誤處理位置。
- **代理後備**: 如果特定條件下需要將請求代理到其他服務器。

#### 使用 `try_files` 與命名位置

```Nginx
server {
    listen 80;
    server_name example.com;

    # 主位置塊
    location / {
        # 嘗試匹配靜態文件，如果找不到則重定向到 @backend
        try_files $uri $uri/ @backend;
    }

    # 定義 @backend 內部重定向位置
    location @backend {
        # 添加自定義標頭
        add_header X-Cache-Status "MISS" always;
        # 設定代理地址
        proxy_pass http://backend_server;
    }
}

```

在這個例子中：

- `try_files $uri $uri/ @backend;` 指示 Nginx 先嘗試匹配 `$uri` 和 `$uri/`，如果都不匹配，則跳轉到 `@backend`。
- 在 `@backend` 位置塊中，添加一個自定義標頭並將請求代理到 `http://backend_server`。

#### 使用 `error_page` 與命名位置

假設你希望在遇到 404 錯誤時顯示自定義的錯誤頁面，並且如果特定條件下（例如 URL 中包含 `/api/`），將請求代理到其他服務器。可以這樣配置：

```Nginx
server {
    listen 80;
    server_name example.com;

    # 主位置塊
    location / {
        # 通常的處理邏輯
        try_files $uri $uri/ =404;
    }

    # 錯誤頁面處理
    error_page 404 /404.html;
    location = /404.html {
        # 內部重定向到 @notfound 位置
        try_files @notfound;
    }

    # 定義 @notfound 內部重定向位置
    location @notfound {
        # 檢查 URL 中是否包含 /api/
        if ($request_uri ~* /api/) {
            # 如果是，代理到 API 服務器
            proxy_pass http://api_server;
        }

        # 否則返回自定義的 404 頁面
        root /usr/share/nginx/html;
        internal; # 表示這個位置只能內部訪問
    }
}

```