前言
翻译整理原文主要内容(非单纯翻译)
原文的目的是让读者对Node.js http处理过程有一个清楚的理解。如果对HTTP请求如何工作、nodejs的事件处理和流不太熟悉,建议先去大致了解。
创建服务
const server = http.createServer();
server.on('request', (request, response) => {
// server对象其实是一个EventEmitter
// 绑定事件,对request事件作处理
});
基础代码如上,引入http模块通过createServer
方法创建一个网络服务object,其内部传入方法为每次请求都会调用的请求handler。
const { method, url, headers } = request;
const userAgent = headers['user-agent'];
当我们处理request请求时,需要根据方法method、请求路径url做出相应的处理,或者是需要请求头做相应的操作,都可以在request中取到。request
对象即为IncomingMessage
的实例。
备注:所有请求头信息都为小写传输无视用户实际如何发送,这样简化了请求头解析工作。重复的头信息可能会被覆盖或者整合到一起用分隔符分割。
Request
关于request body请求体
当发送POST、PUT请求时,请求对象被传入Readable流对象处理,我们可以对其进行流对象操作,例如通过监听data和end事件获取其内容。
let body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
// body在这里包含了整个请求体且作为字符串形式存在
});
这一步可能有些乏味,通常交给npm上的模块工具去完成(例如concat-stream
和body
)
关于error
因为request
对象是一个ReadableStream
流对象,同时又是EventEmitter
可以处理事件。所以自然可以监听error
事件作错误处理。
若没有监听error事件,可能会抛出异常中断Node.js程序
Response
response
对象作为响应用户请求,ServerResponse
的实例,是一个WritableStream流对象
// 单独写状态码、响应头
response.statusCode = 404;
response.setHeader('Content-Type', 'application/json');
response.setHeader('X-Powered-By', 'bacon');
// 整合到一起写响应头
response.writeHead(200, {
'Content-Type': 'application/json',
'X-Powered-By': 'bacon'
});
因为response是流对象,所以可以用流对象方法写内容
response.write('');
response.write('');
response.write('Hello, World!
');
response.write('');
response.write('');
response.end('');
简易demo
const http = require('http');
http.createServer((request, response) => {
const { headers, method, url } = request;
let body = [];
request.on('error', (err) => {
console.error(err);
}).on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
// 开始对response对象进行操作
response.on('error', (err) => {
console.error(err);
});
response.writeHead(200, {'Content-Type': 'application/json'})
const responseBody = { headers, method, url, body };
response.write(JSON.stringify(responseBody));
response.end();
// 结束对response对象操作
});
}).listen(8080); // 激活服务器,监听8080端口
官方还提供了更加详细的demo描述针对method和url不同(即请求对应url做不同的处理)这里不再做过多解释
总结
官方描述了最为基础的处理HTTP请求的方法
- 实例化一个带有request处理函数的HTTP服务并监听端口
- 去请求对象里获取headers, URL, method和body数据
- 基于URL and/or 其他(例如method)订制路由策略
- 通过response对象发送头、状态码和body数据
- 从请求对象到响应对象传输数据
- 同时处理好request和response流的错误信息
通过这些基础特性,许多基础的Nodejs的HTTP服务就可以被建立起来了。node API doc里面也提供了许多方法可供更复杂的场景使用。
参考
Anatomy of an HTTP Transaction