浏览器和 HTTP

正如上例所示,当我们在浏览器地址栏输入一个 URL 后浏览器会发送一个请求。当 HTML 页面中包含有其他的文件,例如图片和 JavaScript 文件时,浏览器也会一并获取这些资源。

一个较为复杂的网站通常都会有 10 到 200 个不等的资源。为了可以很快地取得这些资源,浏览器会同时发送多个GET请求,而不是一次等待一个请求。此类文档都是通过GET方法来获取的。

HTML页面可能包含表单,用户可以在表单中填入一些信息然后由浏览器将其发送到服务器。如下是一个表单的例子。

  1. <form method="GET" action="example/message.html">
  2. <p>Name: <input type="text" name="name"></p>
  3. <p>Message:<br><textarea name="message"></textarea></p>
  4. <p><button type="submit">Send</button></p>
  5. </form>

这段代码描述了一个有两个输入字段的表单:较小的输入字段要求用户输入姓名,较大的要求用户输入一条消息。当点击发送按钮时,表单就提交了,这意味着其字段的内容被打包到 HTTP 请求中,并且浏览器跳转到该请求的结果。

<form>元素的method属性是GET(或省略)时,表单中的信息将作为查询字符串添加到action URL 的末尾。 浏览器可能会向此 URL 发出请求:

  1. GET /example/message.html?name=Jean&message=Yes%3F HTTP/1.1

问号表示路径的末尾和查询字符串的起始。后面是多个名称和值,这些名称和值分别对应form输入字段中的name属性和这些元素的内容。&字符用来分隔不同的名称对。

在这个 URL 中,经过编码的消息实际原本是"Yes?",只不过浏览器用奇怪的代码替换了问号。我们必须替换掉请求字符串中的一些字符。使用%3F替换的问号就是其中之一。这样看,似乎有一个不成文的规定,每种格式都会有自己的转义字符。这里的编码格式叫作 URL 编码,使用一个百分号和16进制的数字来对字符进行编码。在这个例子中,3F(十进制为 63)是问号字符的编码。JavaScript 提供了encodeURIComponentdecodeURIComponent函数来按照这种格式进行编码和解码。

  1. console.log(encodeURIComponent("Yes?"));
  2. // → Yes%3F
  3. console.log(decodeURIComponent("Yes%3F"));
  4. // → Yes?

如果我们将本例 HTML 表单中的method属性更改为POST,则浏览器会使用POST方法发送该表单,并将请求字符串放到请求正文中,而不是添加到 URL 中。

  1. POST /example/message.html HTTP/1.1
  2. Content-length: 24
  3. Content-type: application/x-www-form-urlencoded
  4. name=Jean&message=Yes%3F

GET请求应该用于没有副作用的请求,而仅仅是询问信息。 可以改变服务器上的某些内容的请求,例如创建一个新帐户或发布消息,应该用其他方法表示,例如POST。 诸如浏览器之类的客户端软件,知道它不应该盲目地发出POST请求,但通常会隐式地发出GET请求 - 例如预先获取一个它认为用户很快需要的资源。

我们将在本章后面的回到表单,以及如何与 JavaScript 交互。