Learn 1.1 HTTP Status Code Part.3

by xujiwei(http://www.xujiwei.com/)

前一篇介绍了 3xx 系列状态码,这一篇介绍 4xx 客户端错误系列。

6. 客户端错误 4xx 系列状态码

4xx 系列状态码可以算是对用户来说相当熟悉的一类状态码,这个系列的状态码通常都会带一段描述信息来描述服务端在处理请求时出现了什么状况,用户能直观地看到服务端返回的信息,而不像 3xx 系列,浏览器会自动处理那些个状态码,不需要用户的参与。

但是 4xx 系列状态码之间的区别只是它所代表的意义不同,它们的表现形式是可以随心所欲的,例如一些著名站点的 404 页面都是精心设计过的。

6.1. 400 Bad Request

请求格式错误,这可能存在于客户端构造的 HTTP 头不符合要求等,这时服务端会返回一个 400 Bad Request,而客户端在不修改请求数据的情况,不可以再次发送这个请求。

6.2. 401 Unauthorized

未授权错误,用于 HTTP 认证。如果客户端请求的资源需要认证,那么服务端可以响应一个 401 Unauthorized,同时在头部添加一个 WWW-Authenticate 字段表示认证方式,客户端在收到 401 Unauthorized 时,可以提示用户输入用户名和密码,并根据服务端发送过来的认证方式加密认证数据,再重新发送之前的请求。

HTTP 认证方式中认证数据的传送及格式可以参考 RFC 2617 HTTP Authentication: Basic and Digest Access Authentication

<%@LANGUAGE="JScript" CODEPAGE="65001"%>
<%
// code from www.xujiwei.com
var auth = Request.ServerVariables("HTTP_AUTHORIZATION") + "";
// 判断客户端输入的用户名及密码是否为 hello 及 world
// aGVsbG86d29ybGQ= 是将用户名密码以冒号连接并使用 BASE64 编码后的字符串
if (auth == 'Basic aGVsbG86d29ybGQ=') {
Response.AddHeader("WWW-Authenticate", auth);
Response.Write("Authorized");
}
else {
Response.Status = "401 Unauthorized";
Response.AddHeader('WWW-Authenticate', 'Basic realm=AuthTest');
Response.Write("Unauthorized");
}
%>

6.3. Payment Required

保留的状态码,看字面意思可以在未来用于电子商务之类的网站。

6.4. Forbidden

很直接的,服务端知道客户端想干嘛,但是不想满足它的请求。在服务端XMLHTTP进阶应用-User Agent伪装中有一个简单的例子,使用 ServerXMLHTTP 抓取 Google 新闻的 RSS:

<%@LANGUAGE="JScript" CODEPAGE="65001"%>
<%
// code from www.xujiwei.com
var url = "http://news.google.cn/?output=rss";
var xmlhttp = new ActiveXObject("MSXML2.ServerXMLHTTP.5.0");
xmlhttp.open("GET", url, false);
xmlhttp.send("");
Response.BinaryWrite(xmlhttp.responseBody);
xmlhttp = null;
%>

Google 的服务器很直接的返回了一个 403 Forbidden,也就是说,Google 的服务器知道我的程序想去抓取新闻的 RSS,但 ServerXMLHTTP 默认的 User-Agent 会让 Google 服务端的程序识别出来访问页面的并不是一般的浏览器而是一个 ServerXMLHTTP 组件,这很可能是一些垃圾网站来抓取的,而这是它所不允许的,所以返回一个 403 Forbidden 禁止这种行为。

如果请求的方法不为 HEAD 且请求被禁止的原因可以让客户端知道的话,服务端可以直接在响应中描述请求被禁止的原因,这样客户端就可以显示出来以提示用户是什么原因导致了这次请求被拒绝。如果不提供请求被禁止的原因,服务端可以使用 404 Not Found 来代替 403 Forbidden,这样可以让客户端少一些迷惑。

6.5. 404 Not Found

服务器找不到到对应请求 URI 的任何资源,也不会指出这个情况是暂时的还是永久的。

对用户来说,404 Not Found 这个状态码可以算是最直接的了,一般网址拼错了,服务器很直接的就会发送一个 404 Not Found,通常情况话,可以认为表示用户输入的网址有问题,但事实上是什么情况可能就随服务端程序来定了,如果程序认为用户没有授权查看这个页面,也有可能直接返回一个 404 Not Found,所以,404 Not Found 不是一个很友好的状态码。

所以,如果用户所请求的资源已经永久的被删除了,那么服务器可以返回一个 410 Gone 来代替 404 Not Found。

另外,正如在第一篇里所讲的,如果服务器定义了自定义错误页面,开发者必须注意服务器是否会仍旧发送 404 Not Found 这个状态码,如果不是,那么就需要在程序中指定状态码为 404 Not Found。

6.6. 405 Method Not Allowed

如果收到了这个状态码,表示客户端使用了一个对于所请求的资源来说不被允许的方法,例如在 IIS 里默认情况下是不允许使用 POST 方法来请求静态 HTML 页面的,如果用 POST 方法来请求静态 HTML 页面,IIS 就会返回 405 Method Not Allowed:

test.html

<!-- code from www.xujiwei.com -->
<form action="test.html" method="post">
<input type="text" name="message" /><br />
<input type="submit" value="Submit" />
</form>

在发送 405Method Not Allowed 状态码的同时,服务端也应该在头部中添加一个名为 Allow 的字段,表示请求这个资源所允许的方法,例如上面的代码 IIS 就会返回:Allow : GET, HEAD, OPTIONS, TRACE

因此,如果在开发过程中碰到了 405 错误,可以检查一下服务器的设置,是否对所请求的资源禁止了某些请求方法。

后记

4xx 系列有 18 个状态码,比较多,因此分成几篇来写。

系列目录

Learn HTTP 1.1 Status Code Part.1

Learn HTTP 1.1 Status Code Part.2