11.4. 调试 HTTP Web 服务

首先,让我们启用 Python HTTP 库的调试功能,看看通过网络发送了什么。这在本章中非常有用,因为您将添加越来越多的功能。

示例 11.3. 调试 HTTP

>>> import httplib
>>> httplib.HTTPConnection.debuglevel = 1             1
>>> import urllib
>>> feeddata = urllib.urlopen('http://diveintomark.org/xml/atom.xml').read()
connect: (diveintomark.org, 80)                       2
send: '
GET /xml/atom.xml HTTP/1.0                            3
Host: diveintomark.org                                4
User-agent: Python-urllib/1.15                        5
'
reply: 'HTTP/1.1 200 OK\r\n'                          6
header: Date: Wed, 14 Apr 2004 22:27:30 GMT
header: Server: Apache/2.0.49 (Debian GNU/Linux)
header: Content-Type: application/atom+xml
header: Last-Modified: Wed, 14 Apr 2004 22:14:38 GMT  7
header: ETag: "e8284-68e0-4de30f80"                   8
header: Accept-Ranges: bytes
header: Content-Length: 26848
header: Connection: close
1 urllib 依赖于另一个标准 Python 库,httplib。通常您不需要直接 import httpliburllib 会自动执行此操作),但您需要在此处执行此操作,以便可以在 urllib 内部用于连接到 HTTP 服务器的 HTTPConnection 类上设置调试标志。这是一种非常有用的技术。其他一些 Python 库具有类似的调试标志,但没有特定的命名或启用标准;您需要阅读每个库的文档,以查看是否提供了此类功能。
2 现在已设置调试标志,有关 HTTP 请求和响应的信息将实时打印出来。它告诉您的第一件事是您正在连接到端口 80 上的服务器 diveintomark.org,这是 HTTP 的标准端口。
3 当您请求 Atom 提要时,urllib 会向服务器发送三行内容。第一行指定您正在使用的 HTTP 动词和资源的路径(减去域名)。本章中的所有请求都将使用 GET,但在下一章关于 SOAP 的内容中,您将看到它对所有内容都使用 POST。无论动词是什么,基本语法都是相同的。
4 第二行是 Host 标头,它指定您正在访问的服务的域名。这很重要,因为单个 HTTP 服务器可以托管多个独立的域。我的服务器当前托管 12 个域;其他服务器可以托管数百甚至数千个域。
5 第三行是 User-Agent 标头。您在此处看到的是 urllib 库默认添加的通用 User-Agent。在下一节中,您将看到如何自定义它以使其更具体。
6 服务器使用状态代码和一堆标头进行回复(可能还有一些数据,这些数据存储在 feeddata 变量中)。此处的状态代码是 200,表示“一切正常,这是您请求的数据”。服务器还会告诉您它响应您请求的日期、有关服务器本身的一些信息,以及它提供给您的数据的类型。根据您的应用程序,这可能有用,也可能没用。可以肯定的是,您认为您正在请求 Atom 提要,并且您确实获得了 Atom 提要(application/atom+xml,这是 Atom 提要的注册内容类型)。
7 服务器会告诉您此 Atom 提要的最后修改时间(在本例中,大约是 13 分钟前)。下次您请求相同的提要时,可以将此日期发送回服务器,并且服务器可以执行最后修改检查。
8 服务器还会告诉您,此 Atom 提要的 ETag 哈希值为 "e8284-68e0-4de30f80"。哈希值本身没有任何意义;除了下次请求此相同提要时将其发送回服务器之外,您无法对其执行任何操作。然后,服务器可以使用它来告诉您数据是否已更改。