如果我从一个故事开始,我希望你能原谅我……它提供了一些背景信息。
很久以前(大约 2001/2002 年)我决定需要了解更多有关 Web 编程的知识。我已经知道如何编写 HTML 并将其加载到浏览器中。我听说过这个叫做 CGI 的东西,但它需要我安装一个服务器..我认为我没有时间学习。因此,凭借我的学士学位和一两年的“专业”编程经验,我认为显而易见的事情就是学习 HTTP 的工作原理。
所以我开始阅读 HTTP RFC:https://www.rfc-editor.org/rfc/rfc2616
事实证明,HTTP 确实很简单,但有很多细节......其中大部分都是可选的。我需要一种方法来知道我可以忽略什么以及我必须实现什么,因为我没有时间实现完整的规范(我有一份日常工作要做)。谷歌几年前才问世(太晚了,无法帮助我在大学完成论文,但正好赶上了我的第一份工作),所以我想我应该谷歌“最小的http实现”。如今,您可能会得到不同的结果,但当时它给了我詹姆斯·马歇尔 (James Marshall) 的出色的《HTTP 变得非常简单》(今天仍然在线)。
因此,您要寻找的答案是阅读“HTTP 让一切变得非常简单”页面。
由于 stackoverflow 的政策,我只给你留下一个链接是不礼貌的。不过我仍然强烈建议你阅读那篇文章。无论如何,这是 TLDR:
HTTP 请求只是纯文本。它的简单格式为:
Request Line
Header
Header
Header
Run Code Online (Sandbox Code Playgroud)
HTTP 请求的每个部分都用换行符分隔
注意:从技术上讲,它们应该是
\r\n
,但强烈建议您也接受\n
作为换行符。
注意:从技术上讲,它们应该是 4 字节:
\r\n\r\n
但强烈建议您也接受 2 字节终止符:\n\n
。
请求行的格式为:
METHOD path PROTOCOL_VERSION
Run Code Online (Sandbox Code Playgroud)
METHOD 是 HTTP 方法,例如 POST、GET、PUT、DELETE 等。通常它们应该是大写的。
该路径是通常预期为您请求的文件的路径的 url 路径,但在更现代的情况下,更通常是由 Web 框架处理的端点。
协议版本的格式为:
HTTP/1.1
Run Code Online (Sandbox Code Playgroud)
通常你可以忽略这一点。
请求行的各个部分由空格字符分隔。从技术上讲,应该只有一个空格,尽管我见过发送多个空格的格式严重错误的请求。浏览器绝不会发送多个空格。
标头的格式为:
Header-name: header value
Run Code Online (Sandbox Code Playgroud)
标题名称可以是标题大写或小写或混合,所有这些都是有效的。
知道了这一点,解析 HTTP 实际上相当简单:
// Pseudocode:
let headers = {};
let method = '';
let path = '';
while (1) {
input = read();
buffer.append(input);
if (buffer.contains('\n\n') || buffer.contains('\r\n\r\n') {
raw_request = buffer.split('\n');
request_line = raw_request[0].split(' ');
method = request_line[0];
path = request_line[1];
for (let i=1; i<raw_request.length; i++) {
let header = raw_request[i].split(':');
headers[header[0].toLowerCase()] = header.slice(1).join(':');
}
break
}
}
Run Code Online (Sandbox Code Playgroud)
显然,您不应该使用阻塞while
循环来读取 JavaScript 中的表单 I/O,因为它不起作用,但您已经了解了总体思路。
您还需要处理其他事情,例如读取Content-Length
标头以确定 POST 请求何时完成、如何解析 POST 表单数据(大多数 js 框架不这样做 - 它们要求您使用额外的模块来解析请求) body) 等,但这应该让您从一个最小可行的实现开始,您可以继续添加功能以处理所有不同的请求类型。
归档时间: |
|
查看次数: |
1519 次 |
最近记录: |