HTTP responses
在上一节课的练习中,当输入 Host:localhost
按下两次enter键,服务器发回一堆的文本。这就是一个HTTP响应(HTTP response)。当你的浏览器向服务器请求一个页面,一张图片,或者任何东西,都会发生请求和响应的交换。
其他方法测试一下。使用 ncat 连接到 google.com 80端口,发送一个请求,路径为 / ,在google.com 主机上:
1 | GET / HTTP/1.1 |
确保发送的是 Host: google.com ,不要加上 www 在这里。它们本质上是不同的主机名,我们想要看看它们的区别。按下2次enter键!
(我测试了一下,返回的是”Operation time out.”)
HTTP 响应由三部分组成:状态行,一些头,和响应主体。(the status line,some headers,and a response body)
状态行(status line)是服务器发回的第一行文本。头(headers)是在空白行之前的其他行。响应主体(response body)是剩下的部分 - 在示例中,即这些HTML。
Status line
在之前的示例服务器中,状态行为 HTTP/1.0 200 OK 。在Google的例子中,状态行为 HTTP/1.1 301 Moved Permanently 。状态行告知客户端,服务器是否明白它的请求,服务器是否有它请求的资源,接下来如何继续。它也告知客户端服务器使用的是哪种HTTP方言。
数字200和301是HTTP 状态码(status code)。状态码分为几十种。状态码的第一个数字表明请求的大概结果。为了简写,网页开发人员将所有 2 开头的状态码写为 2xx ,’x’代表任意的数字。
- 1xx - Informational. 该请求正在进行中,或者还有另外的步骤。
- 2xx - Success! 请求成功。服务器正在发送客户端请求的数据。
- 3xx - Redirection. 服务器告知客户端它应该重定向到其他的URI。这些头通常还包含一个指明更新的URI地址(Location)的头。不同的状态码告知客户端重定向是永久的还是临时的。
- 4xx - Client error. 服务器不明白客户端的请求,或不能满足它。不同的状态码告知客户端它是否是一个坏的URI,或者权限问题,或其他的问题。
- 5xx - Server error. 服务器端发生错误。
可在该维基百科页或者这个HTTP规范页查看更多关于HTTP状态码的资料。
Headers
一个HTTP响应可以包含多个头(headers)。每个头都以一个关键字开始一行,比如 Location 或者 Content-type ,接着是一个冒号和值。头相当于是响应的元数据。浏览器或者其他客户端不会展示它们,与之相替的是,它们会告诉客户端各种关于响应的信息。
WEB的很多很多特性都是通过头实现的。例如,cookies 是一个WEB特性,它让服务器将数据保存到浏览器上,如让用户保持登录状态。服务器发送 Set-Cookie 头设置一个cookie。浏览器在之后的请求中会通过一个 Cookie 头将cookie数据发送回服务器。
Content-type 头表明服务器发送的是何种数据,包含一般的类别和具体的格式。例如,一个PNG格式图片的 Content-type 为 image/png 。如果内容是文本,包括HTML,服务器也会告知文本是由哪种方式编码的。UTF-8是常见的选择,也是Python文本的默认编码方式。
头经常会包含更多关于响应主体的元数据。例如,示例服务器和Google都发送了一个 Content-Length 头,这告知客户端响应主体的长度(以bytes计算)。当服务器发送了这条信息,客户端可以在读取第一个响应后重新使用该连接发送另一个请求。浏览器利用这个获取多条数据(比如网页上的很多图片),而不需要重新连接到服务器。
Response body
头部信息以一个空白行结尾。空白行之后的所有内容都是响应主体(response body)。如果该请求是成功的(比如一个 200 OK 状态),响应主体就是客户端请求的任何资源的副本,如网页、图片或者任何其他的数据。
但如果发生错误,响应主体就是错误信息。如果你请求一个不存在的资源,你会得到 404 Not Found 错误,实际的错误显示在响应主体中。
Exercise: Be a web server!
使用 ncat -l 9999 监听9999端口,使用浏览器连接到它 http://localhost:9999/ 。在终端能看到什么?
我的终端出现的是这些信息:
1 | GET / HTTP/1.1 |
接下来,发送一个HTTP响应给你的浏览器,在浏览器发送给你的头下面键入以下内容:
1 | HTTP/1.1 307 Temporary Redirect |
最后,按两次enter键发送一个空白行,表明头的结束。
浏览器会打开eff的主页。
再试一次,运行 ncat -l 9999 充当服务器,让你的浏览器连接到此,但这次,不要发送307重定向,发送 200 OK 和一段文本。
1 | HTTP/1.1 200 OK |
(记住头和主体之间的空白行!)
浏览器会展示你发送的这条信息”Hello, browser! I am a real HTTP server, honestly!”