通过 Node express服务端程序深入了解HTTP请求(二)
上一篇文章中主要演示了HTML5表单发送HTTP请求时的数据处理。这篇文章将把关注点放在后端express应用上。接下来将解析部分express源码来了解expres是如何处理请求的。
代码仓库:https://github.com/jczzq/cool...
express(@4.16.3)
const express = require('express'); const app = express(); // app.use([path,] function [, function...]) app.use('/user/:id', (req, res, next) => { return res.sendStatus(200); });
这是我们的express应用代码,app.use
将挂载一个中间件,处理匹配/user/XXX
路径的所有请求,不管是POST或是GET请求。
- /user 不匹配
- /user?id=233 不匹配
- /user/123 匹配
这个中间件的处理函数是必传参数,处理函数有三个可用参数:
- req: 继承了http.IncomingMessage
- res: 继承了http.ServerResponse
- next: 将控制权交给下一个中间件,如果当前中间件没有终结请求,并且next没有被调用,那么请求将被挂起,后边定义的中间件将得不到被执行的机会。
HTTP请求消息在express中的体现
Node
起始行
之前说过的消息起始行三部分:
- 请求路径 req.url
- http版本 req.httpVersion
- http动作 req.method
三个属性都是继承自Node http API,另外express根据req.url补充完善了多个常用的属性,比如
- req.query:将原本链接上的urlencode编码的参数序列化成了json对象,并且可以通过req.query属性轻松访问。
查看序列化处理源码:https://github.com/expressjs/... - req.params:将原本链接上的/:XX部分处理并序列化成了json对象,可以通过req.params属性轻松访问。
查看源码:https://github.com/expressjs/...
请求头
express中查看原始请求头可以通过req.rawHeaders
或req.headers
获取
- req.rawHeaders 不是express提供的属性,而是继承自Node http.IncomingMessage类,键和值在同一个列表中。偶数位的是键,奇数位的是对应的值。头信息的名称不会被转换为小写,重复的也不会被合并。
- req.headers 头信息的名称与值的键值对。 头信息的名称为小写。原始头信息中的重复数据会按照特定规则进行处理:
curl http://localhost:3000/user/233
输出req.rawHeaders
输出req.headers
请求体
根据express文档描述req.body是唯一用于接收请求体的属性。我们发送请求并返回相关参数,现在我们分别发送application/x-www-form-urlencoded
,multipart/form-data
,text/plain
三个类型的请求体参数看看什么情况。
app.use('/user/:id', (req, res, next) => { return res.json({ query: req.query, params: req.params, body: req.body }); });
application/x-www-form-urlencoded
但实际上没有看到res.body属性的值。
multipart/form-data
multipart/form-data
呢?也没有
text/plain
text/plain
呢?还是没有。看来是没有找到正确的打开方式。
body-parser & multer
body-parser
express处理请求体需要使用专门的解析插件,官方推荐使用body-parser
和multer
,这两个都是用来处理请求体的,不同的是,
multer只处理'multipart/form-data',其余类型的都可以由body-parser处理。拆分开的原因是为了你的应用能更自由地搭配。鉴于web开发中post请求量大,消息体解析频繁,所以[email protected]之前一直都是内置body-parser作为解析器(事实上body-parser的作者TJ也正是express的作者)。
express源码 /lib/express.js
/** * Expose middleware */ exports.json = bodyParser.json exports.query = require('./middleware/query'); exports.static = require('serve-static'); exports.urlencoded = bodyParser.urlencoded /** * Replace removed middleware with an appropriate error message. */ ;[ 'bodyParser', 'compress', 'cookieSession', 'session', 'logger', 'cookieParser', 'favicon', 'responseTime', 'errorHandler', 'timeout', 'methodOverride', 'vhost', 'csrf', 'directory', 'limit', 'multipart', 'staticCache', ].forEach(function (name) { Object.defineProperty(exports, name, { get: function () { throw new Error('Most middleware (like ' + name + ') is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.'); }, configurable: true }); });
最近[email protected]发布了一批新特性,同时也解除了内置的body-parser,只保留了更加常用的两个函数:json
和urlencoded
,你可以通过express全局对象访问这两个解析函数,你基本上再也不用单独引入body-parser了。
multer
var multer = require('multer'); app.use(multer()); // multipart/form-data
multer库是专门为了解决Form上传文件而生的,在body-parser为了遵循渐进式架构理念而放弃解析复杂的multipart/form-data
消息体时,multer应运而生,它使用场景不是很频繁但显然有时候缺它不可。
修改代码如下:
const path = require('path'); const express = require('express'); const app = express(); const multer = require('multer'); // 设置静态文件目录 app.use(express.static(path.resolve('./static'))); console.info('静态文件目录:', path.resolve('./static')); // 首页 app.get('/', function(req, res) { res.sendFile(path.join(__dirname, './index.html')); }); app.use(express.json()); // for parsing application/json app.use(express.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded const upload = multer({ dest: 'uploads/' }); // for parsing multipart/form-data app.use('/user/:id', upload.single('avatar'), (req, res, next) => { return res.json({ query: req.query, params: req.params, file: req.file, body: req.body }); }); app.listen(3000, '0.0.0.0', () => { console.log('启动服务器: http://localhost:3000'); });
选张图片提交
解析成功!
因为multer设置了{ dest: 'uploads/' }
,所以成功保存了图片到指定文件夹内。
参考链接
https://github.com/expressjs/...
https://www.nodeapp.cn/http.html
https://github.com/expressjs/...
http://www.expressjs.com.cn/4...
如有不足 欢迎指正