# Web的历史1️⃣-HTTP
<!--  truncate  -->

*注：这些文章本来是打算作为开发组后端培训文本的开篇而写的，但是我发现文章的内容过于复杂且有点离题，所以稍微修改了一下单独作为3篇独立的文章发布。*

*本文章的许多图片都直接来自 [MDN](https://developer.mozilla.org)，在这里先感谢图片的创作者。*

## 网络的起源
人们最初发明网络的目的很简单：在不同的电脑之间传输文件。那个时候没有U盘，也没有蓝牙，计算机领域的前辈们必须从头设计一个高效的传输文件的办法。

假如我们的电脑上有一个文件`example.docx`,放在我们电脑的文件夹`documents`里面，我们如何使用最原始的方法把它传递给另外一台电脑呢？

早期的程序员编写了一类叫做"HTTP服务器"的程序，程序的功能是选择电脑上的一个文件夹，将这个文件夹暴露在互联网上让所有人操作。这个文件夹叫做HTTP服务的“根目录”。

要使用这个程序，我们还要先给电脑分配一个IP地址，IP地址是一台电脑在互联网上的唯一标识，假如我们电脑的的IP地址是`123.45.67.89`。我们在这台电脑上启动一个HTTP服务程序。在程序的设置里指定根目录是我们存放文件的文件夹`documents`。

前面说过，这个HTTP服务程序的作用是把你电脑上一个指定的文件夹(我们称为“根目录”)暴露在互联网上，所有人都可以下载这个文件夹下的文件。于是这个时候，我们打开随便另一台电脑(前提是有网)，在浏览器地址栏中输入`http://123.45.67.89/example.docx`，这时候就会发生神奇的事情：浏览器会提示你下载`example.docx`,这样，文件就从一台电脑传输到了另一台电脑。

假如`documents`文件夹下面还有另外一个文件`hi.txt`，那么当你在浏览器地址栏中输入`http://123.45.67.89/hi.txt`时，你就会发现浏览器显示了`hi.txt`这份文件的内容，因为浏览器可以直接显示`txt`文件，而不能直接显示`docx`文件。

![IIS根目录](/img/blog/iis-changeroot-websoft9.png)
> *IIS是Windows官方的HTTP服务器，有着图形化的配置界面，其它大部分HTTP服务器都需要通过命令行和配置文件进行配置。*

## HTTP协议

等等，刚才所讲的操作为什么能发生呢？当我在浏览器中输入网址并按下回车键的时候，这一切的背后到底发生了什么？

我们之前提到了，要把电脑中的一个文件夹暴露在网络上供所有人访问，就需要启动一个"HTTP服务程序"，这个HTTP是什么呢？

HTTP协议，是`HyperText Transfer Protocol`的缩写，即"超文本传输协议"。是通过网络在电脑之间进行文件传输的默认协议。进行HTTP文件传输的双方，一个称之为”客户端“(Client),一个称之为"服务端"(Server)。

我们刚才就是在我们的电脑上部署了HTTP服务端，而浏览器就是我们通信中的客户端。浏览器首先对服务器发送信息(行话叫做"请求")，要求获取某个文件；然后服务器返回这个文件(行话叫做“响应”)。

一次完整的HTTP通信总是由客户端请求(Request)和服务端响应(Response)组成。在HTTP协议中，总是由客户端先发起一次HTTP请求，然后由服务端返回这次请求的响应，这样才是一次完整的HTTP通信。

实际上，HTTP协议中的“客户端”不仅仅是指浏览器，但我们通常用的浏览器确实就是最常见的HTTP客户端。但其实像curl这样的命令行工具，或者手机APP，或者是浏览器里的JavaScript代码，当它们向服务器请求数据时，也可以被称作客户端。

![HTTP请求示意图](/img/blog/basic_static_app_server.png)


实际上，HTTP协议不仅可以获取一个文件(就像我们所做的)，也可以向服务端上传一个文件，或是修改某个文件的内容...

一次HTTP通信要进行什么操作(获取or上传等)，由HTTP请求中的“方法”指定，方法是"请求头"的一部分。

"请求头"是什么？别着急，下面我们介绍HTTP协议的具体内容：

### 请求
前面说了，HTTP通信总是以客户端发送请求开始，服务端是没法主动给客户端发信息的。

一个HTTP请求包含请求头(HTTP Request Header)和请求体(Request Body)，请求头主要包含了：

- 协议版本:告诉服务器，这次交流，要使用哪个版本的HTTP协议
- 目标:要访问哪个电脑，例如刚才的`123.45.67.89`
- URI:要操作哪个文件，例如`example.docx`,IP地址或者网址后面的内容就是URI了
- 方法:要对这个文件做什么，比如获取这个文件的内容，还是在服务器上创建这个文件
- 自定义参数：除了上面的信息，客户端还可以发送一些额外的内容给服务端，这些内容总是以`Key=Value`的形式存在。在正常的URI后有一个`?`，表示参数的开始，`&`表示不同参数之间的分隔。

例如：`http://123.45.67.89/example.docx?compressed=true&method=gzip`

这就是让服务器压缩发来的文件，使用gzip压缩。


参数的内容不是HTTP标准，也就是服务端如何理解参数，完全靠程序员写的代码。如果程序员没有设置，那么参数就毫无用处。

#### HTTP方法
HTTP方法定义了这个请求具体要对指定的文件做什么，其中：
- `GET`:获取指定文件的内容。
- `POST`:上传一个文件，内容放在请求体(下面会讲到)。
- `DELETE`:删除某个文件。

其实这里还有一些方法的，我们以后讲。

我们日常使用浏览器，比如在地址栏中输入`baidu.com`,其实就是在对这个地址做GET请求，浏览器会把你的输入内容自动补全成 `GET http://www.baidu.com/` 这一HTTP请求

:::tip 提示

打开浏览器的F12开发者菜单，选择"Network"，可以看到你在访问这个网站时与服务器所进行的所有HTTP请求

:::

在浏览器地址栏里直接输入网址，默认就是发送GET请求。你可能会好奇，POST这些请求是怎么发出去的呢？这通常是由网页中的JavaScript代码在背后发送的。我们在之后的内容会讲到这一点。


![请求头](/img/blog/http-request.svg)

#### 请求体

对于某些方法，需要在请求时向服务器夹带一些东西(比如POST需要你带上新文件的内容)，请求体就是装载这些东西的.

像GET请求就没有请求体，因为GET请求不需要夹带信息.

:::tip[提示]

正常地使用浏览器，是没法做出GET外的请求的，但是浏览器在控制台里可以自定义请求，以`Firefox`为例，在F12的`Network`一栏中点`New Request`(有一个加号)就可以发送自定义请求。`curl`等HTTP命令行工具也可以发送请求.

::: 

### 响应
回应也分为回应头和回应体，回应头主要包含：
- 状态码：针对请求的回应有对应的状态，比如，如果GET请求没有问题，成功返回的话就返回`200 OK`状态码，如果找不到请求里对应的文件就会返回`404 Not Found`
- 内容格式:向浏览器说明回应体（若有）是什么格式的,文本文件的编码设置等，比如html文件？图片？docx文档？有没有被压缩？如果有，压缩格式？这决定了浏览器如何对待这些文件
- 内容的大小：返回所请求资源的大小（若有）

回应体就是包含了回应的主体内容了，如果是GET请求的话，那么就回应了所GET文件的内容，如果是其他请求的话，可能也会没有回应体，具体看使用的方法

![回应体](/img/blog/http-response.svg)

### 例子
`GET`方法从服务器获得一个资源，我们在浏览器的地址栏输入一个地址时，就是在对这个URI做`GET`请求，前面的例子也是通过`GET`方法来进行的。

比如，发送`GET http://developer.zsxyww.com/test/test.txt`,那么就会把我们服务器根目录上`test`文件夹里面的`test.txt`这个文件发过来

`POST`方法向服务器上传一个资源，例如使用某个客户端发送`POST http://example.org/sheet.xlsx`，在request body里面带上你的这个文件，那么`example.org`网站的根目录下就会多出一个叫做`sheet.xlsx`的文件


除了上面介绍的这些方法，还有`DELETE`,`PATCH`等方法，分别对应了删除，修改一个资源，你可以在你的电脑上通过`curl`等程序，或者通过浏览器控制台来进行常规的`GET`之外的方法请求

:::tip[提示]

httpbin.org 这个网站可以让你试验HTTP协议的方法

:::

:::info[HTTPS]

HTTP在网络上是明文传输的，也就是说客户端和服务器之间的每个网络节点，每个人都可以看到。这显然不方便隐私，所以人们发明了HTTPS，也就是把HTTP的正文加密了，HTTPS可以说是当今互联网的基石，有了HTTPS，我们才能放心地在网上输入密码，用银行卡付款等。

:::

## 网页与HTML

随着网络的发展，人们发现互联网的潜力远不止于传输文件。特别是浏览器的普及，人们希望能直接在网页上展示丰富的信息，而不只是把浏览器当作下载工具。前面我们说过了，浏览器可以直接展示txt文件，但是最大的问题是，txt文件是没有样式的。

比如：txt无法设置字体大小和颜色,无法加粗、倾斜文字,无法创建表格和列表,无法插入图片和链接。这些都是txt的局限。

为了解决这个问题，人们发明了HTML(HyperText Markup Language),就是“超文本标记语言”，HTML的核心思想是：在普通文本中加入特殊的标记，告诉浏览器如何显示内容。

比如`<i>你好～</i>`就是指示浏览器以斜体的方式显示`你好～`这段文字。你可以用系统自带的笔记本像打开txt文件一样打开HTML文件，只不过浏览器默认是加载渲染之后的界面而不是原始的HTML。

除HTML之外，人们还发明了CSS与HTML搭配使用，CSS可以对样式做更复杂高级精细的控制，这里就不细说了

回到我们的主题，不管使用的是什么方法，操作的是什么文件，HTTP协议传输的对象都是一些固定静态的文件，其内容在服务器上是固定不变的（除非手动修改），这样的网页称为静态网页。

静态网页中，所有用户看到的内容都相同，内容不会根据用户行为动态变化，服务器只负责传输文件，不进行复杂计算。

我们的wiki就是静态网页，在服务端上都对应着HTML页面，只不过加了非常多的样式显得很高级。

很多常见的网站（如企业官网、技术文档、个人博客等）都是静态网页，虽然看起来很精美，但本质上就是经过精心设计的HTML和CSS文件。

![网页的构成](/img/blog/fetching-a-page.svg)

:::info

这是三篇系列文章中的第**1**篇

点击以跳转：

**HTTP**(你在看的文章)

[动态网页](/blog/Web的历史2️⃣-动态网页)

[Web应用](/blog/Web的历史3️⃣-Web应用)

:::



