koa1.x获取原始body内容

  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堆限制;

     简单,容易实现。

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

  

  

原文地址:https://www.cnblogs.com/cool-fire/p/10100132.html

时间: 2024-10-09 07:31:02

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

JavaScript(19)jQuery HTML 获取和设置内容和属性

jQuery HTML jQuery 拥有可操作 HTML 元素和属性的强大方法. jQuery DOM 操作 jQuery 中非常重要的部分,就是操作 DOM 的能力.jQuery 提供一系列与 DOM 相关的方法,这使访问和操作元素和属性变得很容易. 提示:DOM = Document Object Model(文档对象模型) DOM 定义访问 HTML 和 XML 文档的标准:"W3C 文档对象模型独立于平台和语言的界面,允许程序和脚本动态访问和更新文档的内容.结构以及样式."

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

因为项目的需要以及主管的要求,准备将工程移植到Qt中,这样就可以比较容易的实现跨平台了.因为之前工程是在windows下开发的,第一个平台又是mobile所以除了底层框架之外其他的都是使用的windows的API以及编程模式,现在要移植到Qt中,第一个要面临的问题就是如何将windows的消息机制很好的转换为Qt中的处理机制.windows中是消息,Qt中是事件和信号.槽,其实原理都是一样的. 1.常用事件 因为所有和界面相关的类都是继承自QWidget类,所以QWidget类有的时间和方法,在

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

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 8-6  获取原始对象 问题 你正在使用POCO,想从数据库获取原始对象. 解决方案 假设你有如图8-7所示的模型.你正在离线环境下工作,你想应用在获取客户端修改之前,使用Where从句和FirstDefault()方法从数据库中获取原始对象. 图8-7.包含一个单独实体Item的模型 按代码清单8-9的方式,在获取实体之后,使用新值更新实体并将其保存到数据库中. 代码清单8-9. 获取最新

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

1.phpcms-v9默认情况下只能根据catid获取当前栏目及子栏目下的文章,但是有时候我们需要如何通过{pc}标签来获取全站文章内容的需求,应该怎么做呢? 第一步:在content_tag.class.php文件中添加如下方法: 1 /** 2 * 列表页标签:主要返回的是主表中数据与附表中数据 3 * @param $data 4 */ 5 public function lists_all($data) { 6 $this->db->set_model(1);//将模型手动指定为文章模

Android设备怎么获取扫码枪扫描内容

1. 蓝牙配对,连接设备 打开系统设置,找到蓝牙,打开扫码枪,配对扫码枪设备.输入一个固定的配对码,一般扫码枪说明书里都有写.配对完成后,显示设备已连接.就ok. 2.AndroidManifest中配置权限 android项目中的AndroidManifest.xml文件添加蓝牙权限. <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:na

Qt获取office文件内容

Qt获取office文件内容 需要获取word文件的文件内容.网上找了好久,大部分都是excel的.而word的很少.所以在这里记录一下,方便大家查阅和自己使用. 使用的Qt版本是5.4.2 . 下面通过代码说明: 首先在.pro文件中加入 QT       += axcontainer 需要加入以下头文件 #include <QAxWidget> #include <QAxObject> 详细代码如下 void Qt_word(QString filePath) { //指定要打

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

第二讲 1.创建一个时间格式的单元格 Workbook wb=new HSSFWorkbook(); // 定义一个新的工作簿 Sheet sheet=wb.createSheet("第一个Sheet页"); // 创建第一个Sheet页 //第一个单元格 Row row=sheet.createRow(0); // 创建一个行 Cell cell=row.createCell(0); // 创建一个单元格 第1列 cell.setCellValue(new Date()); // 给

tika获取压缩文件内容

package com.wangchao.tika.sax; import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler; public class MyHandler extends DefaultHandler {    @Override    public void characters(char[] ch, int start, int l

spring mvc controller中获取request head内容

spring mvc controller中获取request head内容: @RequestMapping("/{mlid}/{ptn}/{name}") public String print(@PathVariable Integer mlid, @PathVariable String ptn, @PathVariable String name, HttpSession session, Model model, @RequestHeader String referer,