你照著說明申請了一個 API key,把指令跑下去,得到 401。
或者 403。或者 429。
或者一段你看不懂的英文,裡面有 CORS 或 proxy。
這些都是同一件事的不同面:你的程式與另一台機器之間的一次對話出了問題,而那個對話有固定的格式。看懂格式,錯誤訊息就從天書變成說明書。
一、一次請求長什麼樣子
網路對話的基本單位是請求—回應(request/response)。你問一句,它答一句,然後連線就結束了。
這是理解一切的起點:HTTP 不是「連線」,是「一問一答」。你以為的持續連線,其實是程式在快速地一問一問一問。
一次請求有四個部件:
1. 方法(method) GET(拿資料)/ POST(送資料)/ PUT / DELETE
2. 路徑(path) /v1/chat/completions
3. 標頭(headers) Authorization: Bearer sk-xxxx
Content-Type: application/json
4. 內容(body) {"model": "...", "messages": [...]}
回應也有四個,結構一樣:
1. 狀態碼(status) 200
2. 標頭(headers) content-type: application/json
3. 內容(body) {"choices": [...]}
4. (沒有方法,因為它不是請求)
多數錯誤發生在標頭或狀態碼,而不是內容。 這是第一個實用結論:出錯時先看狀態碼,再看標頭,最後才看內容。
二、狀態碼:三位數,第一位是分類
不需要背。只要記住第一位數字代表什麼:
| 開頭 | 意思 | 你該做什麼 |
|---|---|---|
| 2xx | 成功 | 沒事 |
| 3xx | 轉向(東西搬家了) | 通常程式會自動處理,你不用管 |
| 4xx | 你的錯 | 改你的請求 |
| 5xx | 對方的錯 | 等一會兒重試,或去查對方的狀態頁 |
4xx 與 5xx 的區別是最重要的:4xx 代表重試一百次也是同樣結果(因為問題在你送的東西),5xx 代表等一會兒可能就好了。搞反了會白費很多時間。
幾個你遲早會遇到的:
- 401 Unauthorized —— 你沒證明身分。通常是 API key 沒給、給錯、或放錯位置(該放標頭卻放了別處)。注意:它的意思其實是「未認證」,不是「無權限」,這個命名的歷史包袱害了很多人。
- 403 Forbidden —— 你證明了身分,但沒有權限做這件事。換 key 沒用,要查權限。
- 404 Not Found —— 路徑錯了。最常見的原因是網址少一段或多一段,或版本號不對(
/v1/vs/v2/)。 - 429 Too Many Requests —— 你太快了。這就是速率限制,見 Rate Limit(速率限制)。正確做法是等,或按回應裡給的提示降速;不要用重試轟它,那通常會讓限制更嚴。
- 500 / 502 / 503 —— 對方的伺服器出問題。502/503 通常代表它前面的某一層掛了,等幾分鐘再試。
一個實用習慣:遇到 4xx,把完整的錯誤 body 讀一遍。多數 API 會在 body 裡用人話說明哪裡不對(例如 model not found 或 invalid api key),而那一句比狀態碼有用得多。
三、標頭: metadata,不是內容
標頭是關於這次請求的資訊,不是請求的內容本身。最常見的幾個:
Authorization—— 你的憑證放這裡。幾乎所有的 401 都是這個標頭的問題:缺了、格式不對(例如漏了Bearer前綴)、或者貼了多餘的空白。Content-Type—— 你送的 body 是什麼格式。送 JSON 就要寫application/json。寫錯會讓對方解析失敗,錯誤訊息常常很含糊。User-Agent—— 你是什麼程式。有些服務會擋掉看起來像自動化的 User-Agent,本站在做研究時遇過官方文件站對自動化抓取回 403,就是這個原因。
除錯時怎麼看標頭:
curl -i https://example.com/api/xxx
-i 會把標頭一起印出來。這是最快看清一次請求到底發生了什麼的方法,比讀程式碼快。
四、WebSocket:另一種說話方式
HTTP 是一問一答,問完就斷。但有些東西需要伺服器主動推給你 —— 聊天訊息、即時通知、Agent 的進度回報。
WebSocket 是一條持續開著的雙向通道:連上之後,兩邊都可以隨時送東西,不需要一方先問。
你什麼時候會遇到它:
- 聊天介面(訊息要即時出現)
- Agent 的 gateway(例如把 Agent 接上飛書/Lark 時,官方推薦的正是 WebSocket 長連線,因為不需要公網 IP、也不需要配 webhook)
- 任何顯示「即時」的東西
為什麼這 matters:WebSocket 不需要你的機器對外面開放一個埠,所以在沒有公網 IP 的環境(家裡、公司內網)也能用。這是它對新手最實際的好處 —— 少一大類網路設定問題。
輪詢(polling)是不用 WebSocket 的替代方案:你的程式每隔幾秒問一次「有新東西嗎」。簡單但浪費,而且有延遲。
見 WebSocket(雙向長連線) 與 Request/Response(請求—回應)。
五、CORS:為什麼瀏覽器擋你
你在網頁裡寫了一段程式去呼叫某個 API,得到的錯誤裡有 CORS 或 Access-Control-Allow-Origin。
CORS 是瀏覽器的安全機制:它規定一個網頁只能呼叫「被允許的」其他網站的 API。目的是防止你打開一個惡意網頁時,它在背後偷偷用你的身分去呼叫別的網站。
關鍵事實:CORS 只存在於瀏覽器裡。
所以:
- 同樣一個 API,用
curl或寫在後端程式裡可以成功,在瀏覽器裡卻失敗 —— 這不是 API 壞了,是瀏覽器的規則。 - 你無法從前端「修好」CORS。 需要 API 那邊在回應標頭裡允許你的來源。
- 如果那是你自己的 API,你需要設定它回
Access-Control-Allow-Origin。如果是別人的,你只能從後端去呼叫(繞過瀏覽器)。
初學者最常犯的錯:花幾小時試圖在前端修 CORS。答案是「改成從後端呼叫」,通常五分鐘。
六、Proxy:中間有一層
Proxy 是在你與目標之間轉發請求的一台機器。
你什麼時候會遇到它:
- 公司或學校網路:所有對外流量都經過一層 proxy。這會讓某些工具連不上,而且錯誤訊息常常不會說是 proxy 的問題。
- 需要改變來源地區:某些服務只對特定地區開放。
- 本機開發:很多開發伺服器內建 proxy,把
/api的請求轉到真正的後端,目的是避開 CORS。
實務上最常見的問題:一個工具在家裡能用、在公司不能用。那幾乎總是 proxy 或防火牆。這時候:
- 確認是不是網路問題(用瀏覽器打開同一個網址試試)
- 看那個工具有沒有 proxy 相關的設定項
- 問 IT —— 這不是你能自己修的
見 Proxy(代理伺服器) 與 裝完沒反應 的檢查三。
七、SSH 與私鑰:同一類東西
前面六節都是「程式怎麼跟程式說話」。這一節是「你怎麼安全地證明你是你」。
SSH 是一條加密的通道,最常用來登入遠端機器:
ssh 使用者名稱@機器位址
它用一對金鑰來證明身分,而不是密碼:
- 私鑰(private key)留在你的機器上,絕不外傳
- 公鑰(public key)給對方,讓對方能驗證你
這個「一對」的觀念比 SSH 本身重要,因為它到處都是:
- Git 平台用它免密碼推送
- 某些 API 用它簽名請求
- 加密貨幣錢包是同一套數學
三條不可違反的規則:
- 私鑰永遠不要貼給任何人、任何工具、任何聊天視窗。 包括 AI 工具。一個要求你貼私鑰的服務是詐騙。
- 私鑰不要放進 git repo。 這是洩漏私鑰最常見的方式,而且是不可逆的 —— 一旦推送出去,即使你下一秒刪掉,它已經在歷史裡了。
- 洩漏了就立刻作廢並重發,不要只是改密碼然後希望沒事。
見 Private Key(私密金鑰)、SSH(安全外殼)、我的資料安全嗎。
八、一個統一的除錯順序
不管遇到什麼網路錯誤,按這個順序:
- 看狀態碼的第一位數字 —— 4xx 改自己,5xx 等對方
- 4xx 就讀完整的錯誤 body —— 那裡通常有人話
- 用
curl -i重跑一次 —— 看標頭,排除程式本身的問題 - 在瀏覽器裡打開同一個網址 —— 能開代表網路通,問題在設定;不能開代表網路或 proxy
- 最後才懷疑工具壞了
多數人從第 5 步開始(重裝、換工具),然後花掉一小時,而答案在第 1 步就寫著。
下一步
- 第一次呼叫 LLM API —— 把這篇用在一個真實的 API 上
- 什麼是 API key ——
Authorization標頭裡放的那個東西 - 三層 LLM API 矩陣 —— 進階:不同 API 形態的取捨
- 裝完沒反應 —— 檢查三是網路問題
- HTTP(超文本傳輸協定) / Status Code(狀態碼) / Header(標頭) / WebSocket(雙向長連線) / CORS(跨來源資源共享) / Proxy(代理伺服器) / SSH(安全外殼) / Private Key(私密金鑰) / Request/Response(請求—回應)