深入理解nodejs的HTTP处理流程
文章目录
- 简介
- 使用nodejs创建HTTP服务
- 解构request
- 处理Request Body
- 处理异常
- 解构response
简介
我们已经知道如何使用nodejs搭建一个HTTP服务,今天我们会详细的介绍nodejs中的HTTP处理流程,从而对nodejs的HTTP进行深入的理解。
使用nodejs创建HTTP服务
使用nodejs创建HTTP服务很简单,nodejs提供了专门的HTTP模块,我们可以使用其中的createServer方法来轻松创建HTTP服务:
const http = require('http');const server = http.createServer((request, response) => {// magic happens here!
});
首先createServer方法传入的是一个callback函数,这个callback函数将会在每次服务端接收到客户端的请求时调用。所以这个callback函数,也叫做 request handler.
再看看createServer的返回值,createServer返回的是一个EventEmitter对象。
之前我们也介绍过了EventEmitter,它可以发送和接收事件,所以我们可以使用on来监听客户端的事件。
上面的代码相当于:
const server = http.createServer();
server.on('request', (request, response) => {// the same kind of magic happens here!
});
当发送request事件的时候,就会触发后面的handler method,并传入request和response参数。我们可以在这个handler中编写业务逻辑。
当然,为了让http server正常运行,我们还需要加上listen方法,来绑定ip和端口,以最终启动服务。
const hostname = '127.0.0.1'
const port = 3000server.listen(port, hostname, () => {console.log(`please visit http://${hostname}:${port}/`)
})
解构request
上面的request参数实际上是一个http.IncomingMessage对象,我们看下这个对象的定义:
class IncomingMessage extends stream.Readable {constructor(socket: Socket);aborted: boolean;httpVersion: string;httpVersionMajor: number;httpVersionMinor: number;complete: boolean;/*** @deprecate Use `socket` instead.*/connection: Socket;socket: Socket;headers: IncomingHttpHeaders;rawHeaders: string[];trailers: NodeJS.Dict<string>;rawTrailers: string[];setTimeout(msecs: number, callback?: () => void): this;/*** Only valid for request obtained from http.Server.*/method?: string;/*** Only valid for request obtained from http.Server.*/url?: string;/*** Only valid for response obtained from http.ClientRequest.*/statusCode?: number;/*** Only valid for response obtained from http.ClientRequest.*/statusMessage?: string;destroy(error?: Error): void;}
通常我们需要用到request中的method,url和headers属性。
怎么从request中拿到这些属性呢?对的,我们可以使用ES6中解构赋值:
const { method, url } = request;const { headers } = request;
const userAgent = headers['user-agent'];
其中request的headers是一个IncomingHttpHeaders,它继承自NodeJS.Dict。
处理Request Body
从源码可以看出request是一个Stream对象,对于stream对象来说,我们如果想要获取其请求body的话,就不像获取静态的method和url那么简单了。
我们通过监听Request的data和end事件来处理body。
let body = [];
request.on('data', (chunk) => {body.push(chunk);
}).on('end', () => {body = Buffer.concat(body).toString();// at this point, `body` has the entire request body stored in it as a string
});
因为每次data事件,接收到的chunk实际上是一个Buffer对象。我们将这些buffer对象保存起来,最后使用Buffer.concat来对其进行合并,最终得到最后的结果。
直接使用nodejs来处理body看起来有点复杂,幸运的是大部分的nodejs web框架,比如koa和express都简化了body的处理。
处理异常
异常处理是通过监听request的error事件来实现的。
如果你在程序中并没有捕获error的处理事件,那么error将会抛出并终止你的nodejs程序,所以我们一定要捕获这个error事件。
request.on('error', (err) => {// This prints the error message and stack trace to `stderr`.console.error(err.stack);
});
解构response
response是一个http.ServerResponse类:
class ServerResponse extends OutgoingMessage {statusCode: number;statusMessage: string;constructor(req: IncomingMessage);assignSocket(socket: Socket): void;detachSocket(socket: Socket): void;// https://github.com/nodejs/node/blob/master/test/parallel/test-http-write-callbacks.js#L53// no args in writeContinue callbackwriteContinue(callback?: () => void): void;writeHead(statusCode: number, reasonPhrase?: string, headers?: OutgoingHttpHeaders): this;writeHead(statusCode: number, headers?: OutgoingHttpHeaders): this;writeProcessing(): void;}
对于response来说,我们主要关注的是statusCode:
response.statusCode = 404;
Response Headers:
response提供了setHeader方法来设置相应的header值。
response.setHeader('Content-Type', 'application/json');
response.setHeader('X-Powered-By', 'bacon');
还有一个更加直接的同时写入head和status code:
response.writeHead(200, {'Content-Type': 'application/json','X-Powered-By': 'bacon'
});
最后,我们需要写入response body,因为response是一个WritableStream,所以我们可以多次写入,最后以end方法结束:
response.write('<html>');
response.write('<body>');
response.write('<h1>Hello, World!</h1>');
response.write('</body>');
response.write('</html>');
response.end();
或者我们可以用一个end来替换:
response.end('<html><body><h1>Hello, World!</h1></body></html>');
综上,我们的代码是这样的:
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();// BEGINNING OF NEW STUFFresponse.on('error', (err) => {console.error(err);});response.statusCode = 200;response.setHeader('Content-Type', 'application/json');// Note: the 2 lines above could be replaced with this next one:// response.writeHead(200, {'Content-Type': 'application/json'})const responseBody = { headers, method, url, body };response.write(JSON.stringify(responseBody));response.end();// Note: the 2 lines above could be replaced with this next one:// response.end(JSON.stringify(responseBody))// END OF NEW STUFF});
}).listen(8080);
本文作者:flydean程序那些事
本文链接:http://www.flydean.com/nodejs-http-in-depth/
本文来源:flydean的博客
欢迎关注我的公众号:「程序那些事」最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
深入理解nodejs的HTTP处理流程相关推荐
- linux内核led驱动开发,从Linux内核LED驱动来理解字符设备驱动开发流程
目录 博客说明 开发环境 1. Linux字符设备驱动的组成 1.1 字符设备驱动模块加载与卸载函数 1.2 字符设备驱动的file_operations 结构体中的成员函数 2. 字符设备驱动--设 ...
- 深入理解nodejs中的异步编程
文章目录 简介 同步异步和阻塞非阻塞 javascript中的回调 回调函数的错误处理 回调地狱 ES6中的Promise 什么是Promise Promise的特点 Promise的优点 Promi ...
- 理解nodejs中函数的参数的来由
看一段创建并启动nodejs服务的代码,如下: var http = require('http');http.createServer(function (request, response) {r ...
- 【.NET Core项目实战-统一认证平台】第十二章 授权篇-深入理解JWT生成及验证流程...
上篇文章介绍了基于Ids4密码授权模式,从使用场景.原理分析.自定义帐户体系集成完整的介绍了密码授权模式的内容,并最后给出了三个思考问题,本篇就针对第一个思考问题详细的讲解下Ids4是如何生成acce ...
- 深度学习算法训练和部署流程介绍--让初学者一篇文章理解算法训练和部署流程
目录 1 什么是深度学习算法 2 算法训练 2.1 训练的原理 2.2 名词解释 3 算法C++部署 3.1 嵌入式终端板子部署 3.3.1 tpu npu推理 3.3.2 cpu推理 3.2 服务 ...
- 重新理解Linux交叉编译及编译流程
参考书籍 1.编译原理 2.嵌入式Linux应用开发 文章目录 一.交叉编译背景 二.gcc和arm-linux-gcc的常用选项 1.查询gcc帮助 2.常用gcc选项介绍 3.生成一个可执行文件的 ...
- 从煎鸡蛋的角度理解编程的思维和流程,你适合学吗?
其实很多门外人对编程都是懵懵懂懂的,我们可以先看一张图来理解一下: [思维]就是程序员需要考虑到的各种需求,也就是我们想让计算机帮助我们实现什么. [表达]就是计算机可以看懂的指令也就是0和1. 那怎 ...
- 理解Nodejs的单线程实现高并发原理
组成和架构 Nodejs 的特点是事件驱动.非阻塞I/O.高效.轻量. 我们首先看下 Nodejs 的架构. 最上层的是 Nodejs标准库,由JavaScript实现的api库,位置在 lib 目录 ...
- (翻译)理解NodeJs?
(原文地址 作者: Felix Geisendörfer) 我推荐Node.js给别人,通常得到两种反应:要么恍然大悟,要么感到很困惑. 如果你是第二类人,我尝试着解释一下什么是Node: 命令行工具 ...
最新文章
- php和python写爬虫-一个简单的Python写的XML爬虫
- 程序员的十层楼(第11层)
- 贪心算法之买卖股票的最佳时机 II
- linux下如何产生core,调试core
- Mac OSX中memcached安装测试
- wpf开源ui引用步骤_如何通过7个步骤开源您的学术作品
- RBAC用户角色权限设计方案(转)
- 【数据库】sql连表查询
- 解决docker-compose: command not found
- php连接sql server
- 11计算机专业vb试题答案,11计算机专业VB试题(二).doc
- 【备忘】最新区块链开发入门到精通视频教程下载
- selenium爬取淘宝评论信息
- 霹雳吧啦Wz语义分割学习笔记P4
- 测序深度和覆盖度(Sequencing depth and coverage)
- 数据驱动测试一:使用TestNG进行数据驱动
- Java计算文章多少字_java计算中文字数的代码实例
- SCI (SSCI) 投稿全过程信件模板一览(Cover letter,催稿信,修改稿及回复,感谢信,询问校稿及校稿信) (转)
- 微信小程序 系统复制粘贴文本
- 使用C#启动默认Internet浏览器