From 2c2ea539b193a50923f8c9c528693122a7b05e1c Mon Sep 17 00:00:00 2001 From: thislight Date: Fri, 4 Oct 2024 14:09:28 +0800 Subject: [PATCH] added http101 --- source/{_drafts => _posts}/http101.md | 157 +++++------------- .../http101/devtools-in-menu.png | 0 .../http101/devtools-inspect-request.png | 0 .../{_drafts => _posts}/http101/devtools.png | 0 4 files changed, 44 insertions(+), 113 deletions(-) rename source/{_drafts => _posts}/http101.md (86%) rename source/{_drafts => _posts}/http101/devtools-in-menu.png (100%) rename source/{_drafts => _posts}/http101/devtools-inspect-request.png (100%) rename source/{_drafts => _posts}/http101/devtools.png (100%) diff --git a/source/_drafts/http101.md b/source/_posts/http101.md similarity index 86% rename from source/_drafts/http101.md rename to source/_posts/http101.md index 5cd6294..d865725 100644 --- a/source/_drafts/http101.md +++ b/source/_posts/http101.md @@ -1,18 +1,17 @@ --- title: 超文本传输协议(HTTP)快速入门 -date: 2023-03-21 tags: - - 网络 + - 网络协议 + - HTTP +date: 2023-03-21 00:00:00 --- -- 请求一个页面 -- 用词约定 -- 从零开始的HTTP服务器生涯 -- GET和POST -- 常见HTTP状态码和头简介 -- 从HTTP/1.1到HTTP/3 -- 参考资料和扩展阅读 -- FAQ + +- [请求一个页面](#请求一个页面) +- [用词约定](#用词约定) +- [从零开始的HTTP服务器生涯](#从零开始的HTTP服务器生涯) +- [GET和POST](#GET和POST) +- [参考资料和扩展阅读](#参考资料和扩展阅读) @@ -243,7 +242,7 @@ HTTP头部指的是结束标志(空行)以及之前所有部分,而HTTP头 我们已经了解HTTP请求和响应的结构,从这里开始,我们将使用Python来编写一个简单的HTTP服务器。如果你不会Python,可以看看[Python文档网站上的教程](https://docs.python.org/zh-cn/3/tutorial/index.html)。我们只会使用许多编程语言都具备的概念和特性,用其它编程语言实现应该也不会有太大障碍。 -另外提一句,所有代码都在Fedora 37上使用Python 3.11运行。 +另外提一句,所有代码都在Fedora 37上使用Python 3.11测试,但是程序并没有使用特殊的特性,在其它平台和Python上多半也能正常使用。 你可能没有从零开始写HTTP服务器的经验,让我来为我们将要完成的代码划分几个部分: @@ -715,7 +714,7 @@ HTML不在本文范围,敬请参阅MDN Web Docs相关页面。 如果我们使用HTML的form元素进行请求,POST请求主体使用的格式与我们之前查询键值对的格式相同。键是form元素内input元素name属性的值。 -> 绝大部分情况下,你应该用GET方法展示数据、POST方法只用来记录数据。在刷新POST方法返回的页面时,浏览器需要重新提交请求,并会询问用户是否要这样做(因为这样做很可能会导致不需要的副作用)。大部分情况下,这不是用户想体验的麻烦。 +> 绝大部分情况下,你应该用GET方法展示数据、POST方法只用来记录数据。在刷新POST方法返回的页面时,浏览器需要重新提交请求,并会询问用户是否要这样做(因为这样做可能会导致不需要的副作用)。大部分情况下,这不是用户想体验的麻烦。 > 如果你使用HTML的form直接处理POST提交,你可以在处理POST方法完成后返回[HTTP 303 See Other状态码](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/303)并在`Location`头中指定重新请求的地址,让浏览器用GET方法重新请求并展示相应页面。 > 我们接下来就是采用类似方法。 @@ -848,125 +847,56 @@ DEFAULT_PAGE_HTML = """ 我们的代码尚不完善,你可以试试按以下方向改进。 -#### 处理并发连接 +- 处理并发连接 -当前的代码只能依照顺序一个一个处理连接,你使用多线程或者Python的asyncio让我们的服务器能够并发处理连接。 + 当前的代码只能依照顺序一个一个处理连接,你使用多线程或者Python的asyncio让我们的服务器能够并发处理连接。 -参考资料: + 参考资料: -- [Python文档:threading模块](https://docs.python.org/zh-cn/3/library/threading.html#module-threading) -- [Python文档:asyncio](https://docs.python.org/zh-cn/3/library/asyncio.html#module-asyncio) + - [Python文档:threading模块](https://docs.python.org/zh-cn/3/library/threading.html#module-threading) + - [Python文档:asyncio](https://docs.python.org/zh-cn/3/library/asyncio.html#module-asyncio) -#### 连接复用 +- 连接复用 -当前代码在回应请求之后就直接关闭连接,你可以支持HTTP/1.1式的连接复用来提高连接使用效率。 + 当前代码在回应请求之后就直接关闭连接,你可以支持HTTP/1.1式的连接复用来提高连接使用效率。 -参考资料: + 参考资料: -- [MDN Web Docs:HTTP Keep-Alive](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive) -- [MDB Web Docs:HTTP Connection](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection) + - [MDN Web Docs:HTTP Keep-Alive](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive) + - [MDB Web Docs:HTTP Connection](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection) -#### 增强兼容性 +- 增强兼容性 -我们目前的代码作了一些假设,你可以改进代码以提高对不同客户端的兼容性。 + 我们目前的代码作了一些假设,你可以改进代码以提高对不同客户端的兼容性。 -参考资料: + - 支持[HTTP Transfer-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding),我们的代码中没有支持这种传输方式 -- [MDN Web Docs: HTTP Transfer-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding) +- 包装和抽象 -#### 包装和抽象 + 你可以将HTTP服务器包装起来,甚至进一步包装成可以使用的框架,为用户提供可用的API。例如: -你可以将HTTP服务器包装起来,甚至进一步包装成可以使用的框架,为用户提供可用的API。例如: + ````python + from mymodule import MyServer -````python -from mymodule import MyServer + def handle_index(request): + return request.ok(template="index.html") -def handle_index(request): - return request.ok(template="index.html") + if __name__ == "__main__": + server = MyServer({ + "/": handle_index + }) + server.run() + ```` -if __name__ == "__main__": - server = MyServer({ - "/": handle_index - }) - server.run() -```` + 你还可以试试阅读[Tornado的代码](https://github.com/tornadoweb/tornado),这是一个Python异步Web框架。 -你还可以试试阅读[Tornado的代码](https://github.com/tornadoweb/tornado),这是一个Python异步Web框架。 +- 支持Cookie -#### 支持Cookie + HTTP是一个无状态协议:不同的响应-请求之间没有联系。HTTP Cookie是一项在不同响应-请求之间保留数据的技术。设计一个需要保留数据的功能,并在我们的HTTP服务器中实现它。 -HTTP是一个无状态协议:不同的响应-请求之间没有联系。HTTP Cookie是一项在不同响应-请求之间保留数据的技术。设计一个需要使用Cookie的功能,并在我们的HTTP服务器中实现它。 + 参考资料: -参考资料: - -- [MDN Web Docs:Using HTTP cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) - -## 常见HTTP状态码和头简介 - -我们已经明白了HTTP请求-响应的大致框架,接下来我们要往里面补充一些内容。这里简单列出一些常见HTTP状态码和HTTP头。 - -要进一步了解HTTP的详细信息,可以访问[MDN Web Docs上的HTTP页面](https://developer.mozilla.org/en-US/docs/Web/HTTP)。 - -### 常见HTTP状态码 - -HTTP状态码按信息类别组织: - -- `1XX` 继续 -- `2XX` 成功 -- `3XX` 跳转 -- `4XX` 客户端错误 -- `5XX` 服务器错误 - -比较常见的状态码: - -- `200 OK` 请求成功 -- `204 No Content` 请求成功,但是没有响应主体 -- `303 See Other` 要求客户端以GET请求访问`Location`头中的地址,这个跳转是暂时的 -- `304 Not Modified` 资源没有改变,这个跟条件请求(Conditional Requests)和HTTP缓存相关。 -- `400 Bad Request` 请求有错误 -- `401 Unauthorized` 未验证的请求 -- `403 Forbidden` 请求被服务器拒绝 -- `404 Not Found` 找不到资源 -- `500 Internal Server Error` 内部服务器错误 -- `504 Gateway Timeout` 网关超时 - -### `Content-Length`和`Transfer-Encoding: chunked` - -我们在前面已经了解到`Content-Length`的值是主体长度,接收者可以利用这个主体长度读取主体。HTTP同样也提供了在主体长度不确定时的传输方法,要使用这个传输方法,将头`Transfer-Encoding`的值设置为`chunked`。指定这个传输方法时不再需要设置`Content-Length`。 - -顾名思义,这种方法是“按块传输”,主体可以包含一个或多个块。每个块以十六进制的块大小开头,加上`\r\n`,再加上块内容。发送结束时,发送一个大小为0的块来标识发送已结束。 - -### `Host` - -这个头用于给服务器提供访问的域名。 所有请求都应该带上这个头。 - -### `User-Agent` - -代理用户访问网站的客户端就叫做"User Agent",用户代理。这个头可以给服务器提供客户端信息,但是正在被逐步淘汰,取而代之的是Client Hint标准。 - -### `Accept` - -客户端可以接受的数据类型。 - -### `Accept-Encoding` - -客户端可以接受的数据编码,通常是压缩编码。 - -### `Accept-Language` - -客户端偏好的语言。 - -### `Location` - -在一些状态码中标识下一个目标的位置。 - -## 从HTTP/1.1到HTTP/3 - -本文之前内容主要基于HTTP/1.1。如今,HTTP已经改进出HTTP/2和HTTP/3。这些新版本协议更加高效,更加适合我们当下的使用场景。虽然HTTP/2和HTTP/3与HTTP/1.1相比变化很大,但是基本概念并没有什么变动。 - -敬请阅读:[Web.dev: Introduction to HTTP/2](https://web.dev/performance-http2/)。 - -敬请阅读:[Couldflare: What is HTTP/3?](https://www.cloudflare.com/learning/performance/what-is-http3/)。 + - [MDN Web Docs:Using HTTP cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) ## 参考资料和扩展阅读 @@ -975,6 +905,7 @@ HTTP状态码按信息类别组织: - [Wikipedia: URL encoding](https://en.wikipedia.org/wiki/URL_encoding) - [Wikipedia: Telnet](https://en.wikipedia.org/wiki/Telnet) -### HTTP有关的内容太多了,我记不住 +本文内容主要基于HTTP/1.1。如今,HTTP已经改进出HTTP/2和HTTP/3。这些新版本协议更加高效,更加适合我们当下的使用场景。虽然HTTP/2和HTTP/3与HTTP/1.1相比变化很大,但是基本概念并没有什么变动。 -你不需要记住全部内容,只要大概看看知道能这么做就可以了。人类记忆过程中,忘记是一个正常阶段,不清楚的地方直接查资料就可以了。理论物理学家也不需要记得光在真空中传播的速度。 +- [Web.dev: Introduction to HTTP/2](https://web.dev/performance-http2/) +- [Couldflare: What is HTTP/3?](https://www.cloudflare.com/learning/performance/what-is-http3/) diff --git a/source/_drafts/http101/devtools-in-menu.png b/source/_posts/http101/devtools-in-menu.png similarity index 100% rename from source/_drafts/http101/devtools-in-menu.png rename to source/_posts/http101/devtools-in-menu.png diff --git a/source/_drafts/http101/devtools-inspect-request.png b/source/_posts/http101/devtools-inspect-request.png similarity index 100% rename from source/_drafts/http101/devtools-inspect-request.png rename to source/_posts/http101/devtools-inspect-request.png diff --git a/source/_drafts/http101/devtools.png b/source/_posts/http101/devtools.png similarity index 100% rename from source/_drafts/http101/devtools.png rename to source/_posts/http101/devtools.png