Juney

http & web servers lesson6 http responses

这篇博文是记录学习udacity的课程http & web servers的第六篇。

HTTP responses

在上一节课的练习中,当输入 Host:localhost 按下两次enter键,服务器发回一堆的文本。这就是一个HTTP响应(HTTP response)。当你的浏览器向服务器请求一个页面,一张图片,或者任何东西,都会发生请求和响应的交换。

其他方法测试一下。使用 ncat 连接到 google.com 80端口,发送一个请求,路径为 / ,在google.com 主机上:

1
2
GET / HTTP/1.1
Host: google.com

确保发送的是 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
2
3
4
5
6
7
8
9
GET / HTTP/1.1
Host: localhost:9999
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
DNT: 1
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7

接下来,发送一个HTTP响应给你的浏览器,在浏览器发送给你的头下面键入以下内容:

1
2
HTTP/1.1 307 Temporary Redirect
Location: https://www.eff.org/

最后,按两次enter键发送一个空白行,表明头的结束。

浏览器会打开eff的主页。

再试一次,运行 ncat -l 9999 充当服务器,让你的浏览器连接到此,但这次,不要发送307重定向,发送 200 OK 和一段文本。

1
2
3
4
5
HTTP/1.1 200 OK
Content-type: text/plain
Content-length: 50
Hello, browser! I am a real HTTP server, honestly!

(记住头和主体之间的空白行!)

浏览器会展示你发送的这条信息”Hello, browser! I am a real HTTP server, honestly!”

查看原文