Node版本比较老,koa1.x配合koa-body-parser,默认koa-body-parser会把请求数据转成json对象,

  然而有的时候需要获取原始的内容,不要转换,看波koa-body-parser源码,找到办法。

  办法一:设置请求头Content-type值为:text/plain

  

  这样ctx.request.body就是一个字符串了.

  缺点:要毅端加东西,想到前端的懒惰,较困难,放弃。

  

  继续摸索源码,发现一个办法,代码:

const koa = require('koa');
const router = require('koa-router');
const bodyParser = require('koa-body-parser'); const app = new koa();
const a = new router(); function injectRawBody(rawBodyName) {
return function* (next) {
const ctx = this;
let _rawBody = yield function (done) {
let received = '';
function onData(chunk) {
received += chunk;
}
function onEnd() {
ctx.req.removeListener('data', onData);
ctx.req.removeListener('end', onEnd);
done(null, received);
}
}
ctx.request[rawBodyName] = _rawBody;
yield next;
}
} app.use(injectRawBody('rawBody')); app.use(bodyParser(); const server = require('http').createServer(app.callback());
app.use(a.routes());
a.post('/a', function* () {
const ctx = this;
const body = ctx.request.body;
console.log("ctx.request.body:", body);
console.log("type of ctx.request.body:", typeof body); console.log("raw body:", Buffer.concat(ctx.request.rawBody).toString());
console.log("type of raw body:", typeof ctx.request.rawBody); yield tt.addOrCreate.apply(ctx);
ctx.body = 'success'; });
server.listen(3000);

  运行,看输出,成功把原始内容挂在ctx.request.rawBody上,但ctx.request.body却成了undefined,点解?

  经过细查,发现在koa-body-parser/index.js有一句判断:

  

  因为在上一个中间件,已经耗尽了req对象的数据,所以ended就是true,那也就不会进入之后的解析了。为了一点小私,导致依赖body的功能不能用,不行不行。

  既然我放在body-parser前面不行,那我能放到后面么?像这样:

app.use(bodyParser());
app.use(injectRawBody('rawBody'));

  答案是不行,因为在body-parser设置了req.once,而且即使没有设置once,body-parser只有耗尽了req对象(end事件)才会继续下一个中间件,下一个中间件不能再从已经读完的ReadableStream里重新读数据。

  

  

  再细细看波源码,co、koa-body-parser、co-body、raw-body真没发现什么好方法,这几个库之间的协作太无鏠了,基本上没法hack进去。

  想过伪装一个req对象,跟ctx.req有一样的接口,让koa-body-parser里操作的是这个伪装的对象,完了之后再恢复,但没试出来,暂时放弃。

  束手无措之际,突然想起晚上在stackoverflow上看到有人问过同样的问题,回忆了一下其中一个回答,当时觉得没怎么样,现在想想真是可以用,代码:

const koa = require('koa');
const router = require('koa-router');
const bodyParser = require('koa-body-parser');

const app = new koa();
const a = new router(); function injectRawBody(rawBodyName) {
return function* (next) {
const ctx = this;
let received = [];
function data(chunk) {
received.push(chunk);
}
ctx.req.on('data', data);
ctx.request[rawBodyName] = received;
yield next;
}
} app.use(injectRawBody('rawBody')); app.use(bodyParser(); const server = require('http').createServer(app.callback());
app.use(a.routes());
a.post('/a', function* () {
const ctx = this;
//console.log(ctx.request);
const body = ctx.request.body;
console.log("ctx.request.body:", body);
console.log("type of ctx.request.body:", typeof body); console.log("raw body:", Buffer.concat(ctx.request.rawBody).toString());
console.log("type of raw body:", typeof ctx.request.rawBody); yield tt.addOrCreate.apply(ctx);
ctx.body = 'success'; }); server.listen(3000);

  在injectRawBody中间件,绑定了data事件,接收数据。而body-parser只有在end事件发生时才会resolve,所有在injectRawBody里,获取到的是完事的数据,只是存的是buffer,使用的时候需要转换为字符串。

  优点:没有body-parser那样的限制数据大小,buffer想放多少放多少,不受node堆限制;

     简单,容易实现。

  缺点:需要转换成字符串,不会转的还可能出现乱码。

  

  

koa1.x获取原始body内容的更多相关文章

  1. ASP.NET Core Web APi获取原始请求内容

    前言 我们讲过ASP.NET Core Web APi路由绑定,本节我们来讲讲如何获取客户端请求过来的内容. ASP.NET Core Web APi捕获Request.Body内容 [HttpPos ...

  2. 《Entity Framework 6 Recipes》中文翻译系列 (45) ------ 第八章 POCO之获取原始对象与手工同步对象图和变化跟踪器

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 8-6  获取原始对象 问题 你正在使用POCO,想从数据库获取原始对象. 解决方案 ...

  3. paip.uapi 获取网络url内容html 的方法java php ahk c++ python总结.

    paip.uapi 获取网络url内容html 的方法java php ahk c++ python总结. 各种语言总结比较,脚本php.python果然是方便.简短,实用. uapi : get_w ...

  4. POI教程之第二讲:创建一个时间格式的单元格,处理不同内容格式的单元格,遍历工作簿的行和列并获取单元格内容,文本提取

    第二讲 1.创建一个时间格式的单元格 Workbook wb=new HSSFWorkbook(); // 定义一个新的工作簿 Sheet sheet=wb.createSheet("第一个 ...

  5. java分别通过httpclient和HttpURLConnection获取图片验证码内容

    前面的文章,介绍了如何通过selenium+Tesseract-OCR来识别图片验证码,如果用接口来访问的话,再用selenium就闲的笨重,下面就介绍一下分别通过httpclient和HttpURL ...

  6. 百度编辑器ueditor获取不到内容?请把form放在table等其他元素最外面

    百度编辑器ueditor获取不到内容?请把form放在table等其他元素最外面. <form name="form" method="post" act ...

  7. phpcms-v9 --- 如何通过{pc}标签获取全站文章内容?

    1.phpcms-v9默认情况下只能根据catid获取当前栏目及子栏目下的文章,但是有时候我们需要如何通过{pc}标签来获取全站文章内容的需求,应该怎么做呢? 第一步:在content_tag.cla ...

  8. QWidget类中默认是忽略inputMethodEvent事件(要获取输入的内容就必须使用这个事件)

    因为项目的需要以及主管的要求,准备将工程移植到Qt中,这样就可以比较容易的实现跨平台了.因为之前工程是在windows下开发的,第一个平台又是mobile所以除了底层框架之外其他的都是使用的windo ...

  9. spring mvc controller中获取request head内容

    spring mvc controller中获取request head内容: @RequestMapping("/{mlid}/{ptn}/{name}") public Str ...

随机推荐

  1. C#_IO操作

    1.创建文件夹 //using System.IO; Directory.CreateDirectory(%%1);   2.创建文件 //using System.IO; File.Create(% ...

  2. Json和Map互转,四个包(org.json/net.sf.json/com.google.gson/com.alibaba.fastjson)

    目前使用的(org.json/net.sf.json/com.google.gson/com.alibaba.fastjson)这四种json-map互转,其他的以后在补充.............. ...

  3. 20135220谈愈敏Blog3_构造一个简单的Linux系统MenuOS

    构造一个简单的Linux系统MenuOS 谈愈敏 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1 ...

  4. Linux内核分析 笔记四 系统调用的三个层次 ——by王玥

    一.知识点总结 (一)用户态.内核态和中断 1.内核态:在高的执行级别下,代码可以执行特权指令,访问任意的物理地址,这时的CPU就对应内核态 2.用户态:在低级别的指令状态下,代码 只能在级别允许的特 ...

  5. Linux内核分析——第三周学习笔记20135308

    第三周 构造一个简单的Linux系统MenuOS 计算机三个法宝: 1.存储程序计算机 2.函数调用堆栈 3.中断 操作系统两把宝剑: 1.中断上下文的切换:保存现场和恢复现场 2.进程上下文的切换 ...

  6. 第二阶段Sprint8

    昨天:把视频录制整合到时间提醒里,实现视频提醒 今天:重新规划主界面,把视频录制暂放到主页面里,先实现功能,视频提醒后期再做. 遇到的问题:还是有问题,虽然能运行,但是只能播放,不能录了啊...

  7. js页面实时显示时间

    1.通过getMonth()实现获取月份,从0开始计数,需要+1: 2.通过getDay()实现获取星期天数,从0开始,0表示星期日: 3.通过getDate()获取日期. 4.setTimeout( ...

  8. 新手上路 git你好

    天哪,虽然我是一个学计算机的,但是我发现我的计算机学的真是……好吧不说了,言归正传.​ 这几天一直在着手于git,可能只是学了一个皮毛,结果也是不大尽人意,跟着别人学了学,鼓捣了鼓捣,还是有点小小的收 ...

  9. 【助教】浅析log4j的使用

    有不少童鞋私信我一些在写代码时候遇到的问题,但是无法定位问题出在哪里,也没有日志记录,实际上,写日志是开发项目过程中很重要的一个环节,很多问题都可以从日志中找到根源,从而定位到出错位置,为解决问题提供 ...

  10. 08.基于IDEA+Spring+Maven搭建测试项目--Maven的配置文件settings.xml

    <?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://mav ...