HTTP 狀態碼
所有 HTTP 狀態碼,依類別分組,並說明真正容易搞混的那幾組:301 與 308、401 與 403、502 與 504。
在你的瀏覽器中執行
點一下代碼即可複製。
請求已收到,處理仍在繼續。人工很少會看到這一類。
| 代碼 | 意義 |
|---|---|
| Continue | 可以繼續送出請求主體。這是對 `Expect: 100-continue` 標頭的回應,讓用戶端在送出大型上傳之前,先確認伺服器願意接收。 |
| Switching Protocols | 連線正在切換協定,最常見的是切換到 WebSocket。 |
| Early Hints | 先送出的初步標頭,讓瀏覽器能在真正的回應之前先開始抓取資源。 |
請求已收到、已理解,也被接受了。
| 代碼 | 意義 |
|---|---|
| OK | 成功了。 |
| Created | 成功了,而且產生了新的資源,位址在 `Location` 標頭裡。 |
| No Content | 成功了,而且刻意沒有任何內容要回傳。204 不能帶有主體。硬要送出主體是協定錯誤,有些用戶端會處理得很糟。 |
| Partial Content | 回應 `Range` 請求所送出的部分內容。影片拖曳進度與續傳下載就是靠它運作的。 |
你要的東西在別的地方,或是根本沒有變過。
| 代碼 | 意義 |
|---|---|
| Moved Permanently | 已經永久搬走了,請更新你的連結。301 和 302 允許用戶端在重新導向時把 POST 換成 GET,而瀏覽器確實會這麼做。如果方法必須保留,請改用 308 或 307。 |
| Found | 暫時在別的地方,請繼續使用原本這個網址。 |
| See Other | 請改用 GET 去取另一個網址——表單送出完成後最常見的回應。 |
| Not Modified | 你快取的版本仍然有效,不會回傳主體。 |
| Temporary Redirect | 暫時在別的地方,而且請求方法不能改變。 |
| Permanent Redirect | 永久搬到別的地方,而且請求方法不能改變。 |
請求本身有問題,或是不被允許。改變請求內容可能會有幫助。
| 代碼 | 意義 |
|---|---|
| Bad Request | 伺服器根本看不懂這個請求。 |
| Unauthorized | 你尚未通過身分驗證,伺服器不知道你是誰。名字取錯了:401 的意思是「未驗證身分」,「沒有權限」是 403。401 必須帶上 `WWW-Authenticate` 標頭。 |
| Forbidden | 伺服器知道你是誰,但你就是不能拿到這個東西。重新登入沒有用。如果連「這個資源存在」本身都算機密,回 404 才是比較安全的做法。 |
| Not Found | 這個位址上沒有任何東西。它完全沒有說這東西曾經存不存在。如果你確定它永遠消失了,請用 410。 |
| Method Not Allowed | 這個位址存在,但不接受這個方法。回應必須列出可用的方法。 |
| Conflict | 請求與目前的狀態衝突,例如你正在修改的其實是舊版本。 |
| Gone | 它曾經存在,而且是刻意被移除的,不會再回來。 |
| I'm a teapot | 1998 年愚人節的玩笑,然後就再也沒消失過。 |
| Unprocessable Content | 格式沒問題,但語意上是錯的——例如合法的 JSON 裡有不合法的欄位。 |
| Too Many Requests | 你被限流了,`Retry-After` 會告訴你什麼時候可以再來。 |
請求本身沒有問題,是伺服器沒能處理好。
| 代碼 | 意義 |
|---|---|
| Internal Server Error | 出了問題,而伺服器說不出更具體的原因。 |
| Not Implemented | 伺服器根本不支援這個要求。 |
| Bad Gateway | 代理伺服器向上游詢問,卻拿到一個無法使用的回應。上游有回應,只是回得不對。504 是上游沒有在時限內回應,503 則是這台伺服器自己決定不處理。 |
| Service Unavailable | 暫時不提供服務,可能是超載或正在維護。 |
| Gateway Timeout | 代理伺服器等待上游回應,最後放棄了。 |
沒有符合的狀態碼。
先看第一個數字
類別會告訴你「問題出在誰身上」,以及「重試有沒有意義」:
- 1xx——已收到,還在處理中。人工幾乎不會遇到。
- 2xx——成功了。
- 3xx——東西在別的地方,或是根本沒變。
- 4xx——你的請求有問題或不被允許。再送一次一模一樣的東西沒有用。
- 5xx——伺服器沒能處理好。同樣的請求過一陣子很可能就會成功。
最後那個區別,在出事時最有用。4xx 表示先停下來檢查你送了什麼;5xx 表示請求本身沒問題, 重試是合理的。
最常被搞混的幾組
**401 的名字取錯了。**它的意思是尚未驗證身分——伺服器不知道你是誰——而且必須帶上
WWW-Authenticate 標頭。「沒有權限」是 403。重新登入能解決 401,對 403 完全沒用。
**機密資源該回 403 還是 404?**如果「這個資源存在」這件事本身就是機密,回 404 比較安全: 403 等於承認那裡確實有東西。
**404 沒有說任何關於過去的事。**如果你確定那個東西是被刻意、永久移除的,請用 410——它會 讓爬蟲停止再來詢問。
**502、503、504 是三種不同的失敗。**上游回了但回得不對、這台伺服器自己決定不處理、上游 沒有在時限內回應。
重新導向會換掉你的方法,這一點常讓人意外
301 和 302 允許用戶端在跟隨重新導向時把 POST 換成 GET,而每一個瀏覽器都確實這麼做。 所以如果你用 302 去重新導向一個表單送出,主體在抵達時就已經不見了。
307 和 308 的存在正是為了禁止這件事。它們分別等同於 302 和 301,只是多了一項保證:方法 與主體必須原封不動地保留。只要重新導向可能載著 POST,就用 307 或 308。
303 則是刻意反過來:它告訴用戶端改用 GET 去取另一個位址,這正是表單完成後應該給的回應, 讓瀏覽器停在一個可以安全重新整理、而不會重複送出的結果頁。
418 是真的存在,某種意義上
418 I'm a teapot 來自 1998 年的愚人節 RFC,然後就再也沒消失。它不是真正的狀態碼,而且
曾經有人提案把它從註冊表中移除,卻因為實作它的人太多而被否決。伺服器偶爾真的會拿它來表示
「我就是不做這件事」。