Pingclairfile 在載入時編譯一次，成為伺服器實際執行的執行期狀態。由此產生兩個結果，也解釋了這個專案大部分的行為：設定能決定的事都在第一個請求之前完成；而無法被滿足的設定會讓伺服器停止，而不是在請求當下妥協。

## 🗂️ 檔案結構

檔案包含一個選用的 global options 區塊，後面接著一或多個 site block。

```caddyfile
{
    email admin@example.com
}

example.com {
    encode zstd gzip
    reverse_proxy 10.0.0.10:8080 10.0.0.11:8080
}

:8080 {
    file_server ./public
}
```

- **Global options** 寫在檔案最前面、沒有名稱的區塊裡，用於設定不屬於單一 site 的狀態：ACME 帳號信箱、Admin API、自動 HTTPS 行為、trusted proxies，以及主機名上游的 DNS 重新解析。可用選項列在[指令參考](/zh-TW/reference/directives/#global-options)。
- **Site block** 以位址命名：主機、連接埠，或兩者兼具。連接埠屬於位址的一部分，而不是另一個獨立指令，因此只有一個地方需要保持兩者一致。
- **Directive** 是 site block 內的敘述句。有些接受參數串列，有些接受巢狀區塊，有些兩者都接受。
- **註解**以 `#` 開始，延伸到行尾。
- **含空白的值要加引號。** 時間長度要帶單位：`30s` 是三十秒，而在需要時間長度的地方寫裸數字 `30` 會被拒絕。

## 🧭 Matcher

Matcher 用來選出某個 directive 要套用到哪些請求。具名 matcher 以 `@name` 宣告，之後以名稱引用：

```caddyfile
example.com {
    @api path /api/*
    header @api Cache-Control "no-store"

    @assets path /assets/*
    header @assets Cache-Control "public, max-age=31536000, immutable"
}
```

`handle` 區塊依路由群組化行為，並支援不帶 matcher 的 fallback：

```caddyfile
example.com {
    handle /assets/* {
        file_server ./assets
    }

    handle {
        respond "Page Not Found" 404
    }
}
```

## 🧩 Snippet 與 import

Snippet 是可重複使用的片段，以 `(name) { ... }` 宣告，並用 `import name` 引入。Snippet 也能接收呼叫端提供的區塊，並把它插入到片段中寫 `{block}` 的位置：

```caddyfile
(site) {
    https://{args[0]} {
        {block}
    }
}

import site example.com {
    reverse_proxy 127.0.0.1:3000
}
```

在被 import 的檔案裡定義的 snippet，對之後的 import 是可見的。放在參數串列中的 placeholder 會被拒絕，因為 directive 樹無法像 token 層那樣在插入後重新解析該行。

## 🛡️ 驗證

`pingclair validate` 會編譯檔案並套用語意檢查：指令參數、matcher 語法、憑證與金鑰路徑，以及諸如「哪些對端可以宣稱用戶端身分標頭」之類的策略限制。

失敗一律明確且封閉：

- **未實作的名稱會以名稱拒絕。** 格式定義的每個名稱都會被辨識，伺服器未實作的會產生「功能不存在」的訊息。它不會被當成拼字錯誤，也不會被忽略：含有這類名稱的設定不會啟動。
- **無法兌現的選項會被拒絕，而不是降級。** 例如在 `encode` 中指定 Brotli 會是編譯錯誤，因為代理沒有串流 Brotli 編碼器；伺服器不會悄悄改用 gzip。
- **語法正確但引用不存在素材的檔案仍會被拒絕。** 倉庫中的 `examples/full_featured.pingclair` 是合法的 Caddyfile 語法，但仍然會被拒絕，而且理由正確：它指名的憑證路徑不存在於執行檢查的機器上。

同樣的檢查會在載入時執行，因此重新載入時若設定驗證失敗，先前的狀態會保持不變。

## 🔁 重新載入

`pc service reload` 會重新讀取設定，而不重啟行程。於啟動階段建立的行程級策略，例如 `trusted_proxies`，要在重啟後才會生效。
