如何在LoopBack中使用body-parser?

25

我发现 LoopBack 内置了 Express 3.x 中间件。确实,在 loopback/node_modules 中有 body-parser。但是我无法弄清楚如何将其用作中间件。我从未使用过 Express 3.x,所以可能就是这个原因。在 server.js 中使用 require 显然行不通,除非我在项目中安装 body-parser 作为依赖项。

那么我应该在 server.js 中做什么才能使用 body-parser,以便将 Web 表单解析为 req.params?它就是这样工作的,对吗?


如何在LoopBack 4中实现? - Kannan T
8个回答

57

在经历数个小时的挫败后,我只是像这样将它添加到 middleware.json 中:

"parse": {
    "body-parser#json": {},
    "body-parser#urlencoded": {"params": { "extended": true }}
}

它已作为依赖项安装。现在我的路由中有表单数据在req.body中。我的server/boot/routes.js看起来像这样:

module.exports = function(app) {
    app.post('/mailing_list', function(req, res) {
        console.log(req.body.email);
        res.send({"status": 1, "message": "Successfully added to mailing list."})
    });
}

26

为了更清楚地说明如何使其工作(因为即使找到答案后我仍然苦苦挣扎了一段时间!),以下是我所采取的步骤:

如上所述,在 $APP_HOME/server/middleware.json 中,将 body-parser 添加到“parse”部分:

{
  "initial:before": {
    "loopback#favicon": {}
  },
  "initial": {
    "compression": {},
    "cors": {
      "params": {
        "origin": true,
        "credentials": true,
        "maxAge": 86400
      }
    }
  },
  "session": {
  },
  "auth": {
  },
  "parse": {
    "body-parser#json": {},
    "body-parser#urlencoded": {"params": { "extended": true }}
  },
  "routes": {
  },
  "files": {
  },
  "final": {
    "loopback#urlNotFound": {}
  },
  "final:after": {
    "errorhandler": {}
  }
}

接下来,我将解析器设置添加到$APP_HOME/server/server.js中:

var loopback = require('loopback');
var bodyParser = require('body-parser');
var multer = require('multer');

var boot = require('loopback-boot');

var app = module.exports = loopback();

app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.use(multer()); // for parsing multipart/form-data

app.start = function() {
...
...
cont'd

那么,由于我不想乱搞自定义路由,我将以下内容添加到$APP_HOME/common/models/model.js中:

module.exports = function(Model) {

  Model.incoming = function(req, cb) {
    cb(null, 'Hey there, ' + req.body.sender);
  }
  Model.remoteMethod(
    'incoming',
    { accepts: [
      { arg: 'req', type: 'object', http: function(ctx) {
        return ctx.req;
      } 
    }],
    returns: {arg: 'summary', type: 'string'}
    }
  );
};

我现在可以使用$> slc run . 运行我的应用程序。

当我向端点提交请求时,它现在被正确地解析,这个世界一切都好。希望这能帮助其他人!


1
您,先生,是一个传奇。 - Daryl Rodrigo
1
谢谢你,我被卡在这个问题上好几个小时了! - Dan
应该被接受的答案。对我有用!谢谢@Ben Carlson - Mike S.
7
这个对我来说甚至没有启动。具体而言,这一行代码:app.use(multer()); // for parsing multipart/form-data,除非我添加一个函数multer().any(),否则它不起作用 - 否则会收到错误信息“要求中间件函数”。 - Anselan
我可以问一下 - 如果您的端点是使用内置模型的话,它的URL是什么?只是想弄清楚在API中是否有一个与数据模型无关的端点是否有任何优势,或者是否只需要在引导脚本路由中就可以了。我的限制是URL中不能有斜杠。 - Stev_k
3
如其他评论中所指出的,你不需要在 server.js 和 middleware.json 中都指定解析配置。后者是首选方法。 - Luke W

9
我正在使用loopback 2.14.0:
为了在自定义的bootscript路由中使用body-parser,您只需要:
1)安装body-parser npm install body-parser --save 2)在middleware.json中注册该模块。
"parse": {
"body-parser#json": {},
"body-parser#urlencoded": {"params": { "extended": true }}
},

当您注册中间件时,无需在server.js中设置解析器,loopback会为您完成此操作。

请注意,body-parser现在已安装在您的源“node_modules”目录以及loopback模块目录中。

如果可能,请按照loopback文档中所述注册自定义远程方法。

通过这种方式注册路由可让您直接使用loopback的body-parser,并且是最“清晰”的实现方式。


4
根据Ben Carlson提供的答案https://dev59.com/CF4b5IYBdhLWcg3w7Fgv#29813184,您需要进行以下操作:
npm install --save body-parser multer

在你的 server.js 中导入模块:
var bodyParser = require('body-parser');
var multer = require('multer');

在 app.start 之前使用它们:

app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.use(multer().any()); // for parsing multipart/form-data

然后您可以创建一个远程方法:
App.incoming = function (req, cb) {
    console.log(req);
    // the files are available as req.files.
    // the body fields are available in req.body
    cb(null, 'Hey there, ' + req.body.sender);
}
App.remoteMethod(
    'incoming',
    {
    accepts: [
        {
        arg: 'req', type: 'object', http: function (ctx) {
            return ctx.req;
        }
        }],
    returns: { arg: 'summary', type: 'string' }
    }
);

使用此功能,您可以使用multipart/form-data将文件和附加数据字段上传到loopback。

2

我发表这篇文章只是为了提供信息。我也遇到过这个问题,发现以下方法同样有效。你可以在server/boot/目录下添加一个文件,内容如下:

var bodyParser = require('body-parser');

module.exports = function(app) {
  app.use(bodyParser.urlencoded({ extended: true }));
}

当然,您需要通过运行以下命令来安装该软件包:
npm install --save body-parser

这将会把包保存在node_modules目录下。 如果你希望它是第一个被运行的东西,你可以以“0”开头来命名文件,因为这些文件是按照字母顺序加载的。

话虽如此,我认为使用上面提到的中间件配置方法比这个更加“正确”和优雅,但是我分享它是为了让其他人也能从中受益。


2

In Loopback ^3.22.0, I can suffice by adding the

"parse": {
    "body-parser#json": {}
  },

将应用程序/JSON POST主体传递到服务器/中间件.json以便在server/boot/routes.js中消费。"Original Answer"的翻译是"最初的回答"。
module.exports = function(app) {
  app.post('/api/sayhello', function(req, res, next) {
     console.log(req.body)

1

你也可以在Loopback中使用Express框架的内置解析器来进行JSON解析,例如:

app.use(app.loopback.json());

0

我有不同的测试结果。

1) 对于json和urlencode类型,无需在middleware.json中添加它们的解析器。我可以成功地从req.body获取数据,而无需添加body-parser#json和body-parser#urlencoded。Loopback应该已经支持它们。

Loopback相关源代码(我认为)

1. in strong-remote repo , rest-adapter.js , there is body-parser for json and urlendcoded

line 35
var json = bodyParser.json;
var urlencoded = bodyParser.urlencoded;

line 315
root.use(urlencoded(urlencodedOptions));
root.use(json(jsonOptions));

2. 
remote-object.js
line 33
require('./rest-adapter');

line 97
RemoteObjects.prototype.handler = function(nameOrClass, options) {
var Adapter = this.adapter(nameOrClass);
var adapter = new Adapter(this, options);
var handler = adapter.createHandler();

if (handler) {
// allow adapter reference from handler
handler.adapter = adapter;
}

return handler;
};

2) 对于原始类型,我们可以在middleware.json的“parse”部分中添加body-parser#raw,当然,需要npm安装body-parser。

我的测试代码:

1.My readable stream is from the file uploadRaw.txt , the content is :
GreenTeaGreenTeaGreenTeaGreenTeaGreenTeaGreenTeaGreenTeaGreenTeaGreenTeaGreenTeaGreenTeaGreenTeaGreenTeaGreenTeaGreenTeaGreenTeaEeeeend

2. middleware.json
"parse": {
"body-parser#raw": {
"paths": [
"/api/v1/Buckets/?/upload"
]
}
},

3.
it('application/octet-stream -- upload non-form', () =>
new Promise((resolve) => {

const options = {

method: 'POST',

host: testConfig.server.host,

port: testConfig.server.port,

path: ${appconfig.restApiRoot}/Buckets/${TEST_CONTAINER}/upload,

headers: {

'Content-Type': 'application/octet-stream',

},
};

const request = http.request(options);

request.on('error', (e) => {
logger.debug(problem with request: ${e.message});
});

const readStream = fs.createReadStream('tests/resources/uploadRaw.txt');

readStream.pipe(request);

resolve();
}));

4.
Bucket.upload = (req, res, options, cb) => {

logger.debug('sssssss in uploadFileToContainer');

fs.writeFile('/Users/caiyufei/TEA/green.txt', req.body, (err) => {

if (err) {

logger.debug('oh, failed to write file');

return;
}

logger.debug('green file is saved!');
});

};

OR

Bucket.upload = (req, res, options, cb) => {

logger.debug('sssssss in uploadFileToContainer');

const writeStream = fs.createWriteStream('/Users/caiyufei/TEA/green.txt');

const streamOptions = {
highWaterMark: 16384,`enter code here`
encoding: null,
}

streamifier.createReadStream(Buffer.from(req.body), streamOptions).pipe(writeStream);

};

5. package.json

"body-parser": "^1.17.1",

"streamifier": "^0.1.1",

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接