}
console.log(decode('a=1&b=2&c=3')) // { a: '1', b: '2', c: '3' }
URL编码方式适合处理简单的键值对数据,并且很多框架的Ajax中的Content-Type默认值都是它,但是对于复杂的嵌套对象就不太好处理了,这时就需要JSON编码方式大显身手了。
客户端发送请求主体时,只需要采用JSON.stringify进行编码。服务器端只需要采用JSON.parse进行解码即可:
const strictJSONReg = /^[x20x09x0ax0d]*([|{)/;
function parse(str) {
if (!strict) return str ? JSON.parse(str) : str;
// 严格模式下,总是返回一个对象
if (!str) return {};
// 是否为合法的JSON字符串
if (!strictJSONReg.test(str)) {
throw new Error('invalid JSON, only supports object and array');
}
return JSON.parse(str);
}
除了上述两种字符串编码方式,koa-bodyparser还支持不采用任何字符串编码方式的普通字符串。
三种字符串编码的处理方式由【co-body】模块提供,koa-bodyparser中通过判断当前Content-Type类型,调用不同的处理方式,将获取到的结果挂载在ctx.request.body:
return async function bodyParser(ctx, next) {
if (ctx.request.body !== undefined) return await next();
if (ctx.disableBodyParser) return await next();
try {
// 最重要的一步 将解析的内容挂载到koa的上下文中
const res = await parseBody(ctx);
ctx.request.body = 'parsed' in res ? res.parsed : {};
if (ctx.request.rawBody === undefined) ctx.request.rawBody = res.raw; // 保存原始字符串
} catch (err) {
if (onerror) {
onerror(err, ctx);
} else {
throw err;
}
}
await next();
}; async function parseBody(ctx) {
if (enableJson && ((detectJSON && detectJSON(ctx)) || ctx.request.is(jsonTypes))) {
return await parse.json(ctx, jsonOpts); // application/json等json type
}
if (enableForm && ctx.request.is(formTypes)) {
return await parse.form(ctx, formOpts); // application/x-www-form-urlencoded
}
if (enableText && ctx.request.is(textTypes)) {
return await parse.text(ctx, textOpts) || ''; // text/plain
}
return {};
}
};
其实还有一种比较常见的Content-type,当采用表单上传时,报文主体中会包含多个实体主体:
------WebKitFormBoundaryqsAGMB6Us6F7s3SF
Content-Disposition: form-data; name="image"; filename="image.png"
Content-Type: image/png------WebKitFormBoundaryqsAGMB6Us6F7s3SF
Content-Disposition: form-data; name="text"
------WebKitFormBoundaryqsAGMB6Us6F7s3SF--
这种方式处理相对比较复杂,koa-bodyparser中并没有提供该Content-Type的解析。(下一篇中应该会介绍^_^)









