【问题标题】:Sending HTTP Post request from node to Foxx service (ArangoDB)将 HTTP Post 请求从节点发送到 Foxx 服务(ArangoDB)
【发布时间】:2017-07-14 14:27:09
【问题描述】:

我正在尝试从节点 + 快递服务器向我在 Arangodb 上的 Foxx 服务发送发布请求。

在节点端:

var route = arangopi + '/edge/' + col.name ;
var body = {data: data, from: fromId, to: toId} ;
console.log('|| body :', route, body) ;

>> || body : http//XXX/_db/my-DB/my-foxx-service/path/to/visitedBy { data: { isBackup: true, text: '', isHint: true, continuance: 3441.5 }, from: 'Drop/27237133', to: 'Bot/41116378' }

return requestify.post (route, body)

在 Foxx 方面,我收到了请求,但日志告诉我它没有正文:

router.post('/path/to/:param', function (req, res) {
  console.log ('|| body :', req.body)
  var data = req.body ;
  var result = api.DoSomething (req.stateParams.param, data)
   res.send(result)
})
.response(joi.object().required(), 'Entry stored in the collection.')
.summary('Summary')
.description('Description') 

>>  || body : [Object { "binarySlice" : function binarySlice() { [native code] }, "asciiSlice" : function asciiSlice() { [native code] }, "base64Slice" : function base64Slice() { [native code] }, "ucs2Slice" : function ucs2Slice() { [native code] }, "hexSlice" : f...

在节点方面,我也尝试了“请求”模块。

return request.post(route, {form:body}, function (error, response, body) {
  console.log('error:', error);
  console.log('statusCode:', response && response.statusCode);
  console.log('body:', body);
  return response ;
});

我从 Foxx 得到相同的日志。

我做错了什么?

这是我在 Foxx 界面上的操作截图。无法指定请求正文进行测试是否正常?

【问题讨论】:

  • 你是否从 node.js 端尝试过这个:return requestify.post (route, JSON.stringify(body));
  • @DavidThomas 谢谢我试过了,但没用
  • 在 Foxx 方面怎么样,在 req.body 上尝试 JSON.stringify 或 JSON.parse。你也可以试试request模块,我用它从node.js调用Foxx服务,没有任何问题,运行良好。
  • @DavidThomas 我试过了,但没有成功。我复制了问题中的“请求”代码,你看到错误了吗?我现在正在尝试其他库。奇怪的是,我收到的请求没有包含所有库的正文!
  • @DavidThomas 当您检查您的查询时,您是否获得相同的 Web 界面参数?还有一个“身体”吗?

标签: node.js http arangodb foxx requestify


【解决方案1】:

正如 David Thomas 在他的回答中解释的那样,我需要在我的路由器代码(Foxx 端)中指定正文格式。

简而言之:

const bodySchema = joi.object().required().description('Data Format');

router.post('/path/to/:param', function (req, res) {
  var data = req.body ;
  var result = api.DoSomething (req.stateParams.param, data)
  res.send(result)
})
.body(bodySchema, 'Body data')
.response(joi.object().required(), 'Entry stored in the collection.')
.summary('Summary')
.description('Description')    

【讨论】:

    【解决方案2】:

    我认为原因是因为您没有在 Foxx 的末尾指定作为 .post 一部分的正文。

    我花了一段时间想出一种定义 Foxx 微服务的方法,并且在确定一个模式之前,我通读了许多 ArangoDB 示例代码。

    为了帮助您入门,我提供了如何以可扩展的方式快速模拟 Foxx 微服务代码,允许您将路由与模型分开。

    使用这些作为示例,让您的示例发挥作用。

    我假设有两个文档集合,“Drop”和“Bot”,以及一个连接它们的边缘集合,称为“VisitedBy”。

    所有这些文件都存储在您的 Foxx 微服务中:

    main.js

    'use strict';
    module.context.use('/v1/visitedBy', require('./routes/visitedBy'), 'visitedBy');
    

    routes/visitedBy.js

    'use strict';
    const request = require('@arangodb/request');
    const joi = require('joi');
    const createRouter = require('@arangodb/foxx/router');
    const VisitedBy = require('../models/visitedBy');
    
    const visitedDataSchema = joi.object().required().description('Data that tracks a visited event');
    
    const router = createRouter();
    module.exports = router;
    
    
    /*********************************************
     * saveVisitedBy
     * Path Params:
     * none
     * Query Params:
     * none
     * Body Params:
     * body         (required)    The data that is used to record when something is visited
     */
    router.post('/', function (req, res) {
      const visitedData = req.body;
      const savedData = VisitedBy.saveVisitedByData(VisitedBy.fromClient(visitedData));
      if (savedData) {
        res.status(200).send(VisitedBy.forClient(savedData));
      }  else {
        res.status(500).send('Data not saved, internal error');
      }
    }, 'saveVisitedBy')
      .body(visitedDataSchema, 'visited data')
      .response(VisitedBy.savedDataSchema, 'The response after the data is saved')
      .summary('Save visited data')
      .description('Save visited data');
    

    models/visitedBy.js

    'use strict';
    const _ = require('lodash');
    const joi = require('joi');
    const db = require('@arangodb').db;
    const visitedByEdgeCollection = 'VisitedBy';
    
    /*
     Schema for a response after saving visitedBy data
     */
    const savedDataScema = {
      id: joi.string(),
      data: joi.object(),
      _from: joi.string(),
      _to: joi.string()
    };
    
    module.exports = {
      savedDataSchema: savedDataScema,
    
      forClient(obj) {
        // Implement outgoing transformations here
        // Remove keys on the base object that do not need to go through to the client
        if (obj) {
          obj = _.omit(obj, ['_id', '_rev', '_oldRev', '_key']);
        }
    
        return obj;
      },
    
      fromClient(obj) {
        // Implement incoming transformations here
        return obj;
      },
    
      saveVisitedByData(visitedData) {
        const q = db._createStatement({
          "query": `
                INSERT {
                  _from: @from,
                  _to: @to,
                  data: @data,
                  date: DATE_NOW()
                } IN @@col
                RETURN MERGE ({ id: NEW._id }, NEW)
          `
        });
        q.bind('@col', visitedByEdgeCollection);
        q.bind('from', visitedData.from);
        q.bind('to', visitedData.to);
        q.bind('data', visitedData.data);
    
        const res = q.execute().toArray();
    
        return res[0];
      }
    };
    

    您的服务在 Swagger 界面中应如下所示:

    您可以了解更多关于使用 joi 定义数据结构here

    需要一点时间来适应 joi,但是一旦你获得了一些好的工作示例,你就可以为传入和传出数据定义出色的数据定义。

    我希望这会有所帮助,我很难获得一个基本的微服务代码模型来清楚地说明事情是如何运作的,我相信这个示例可以做很多事情,但它应该是一个很好的起点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-18
      • 2011-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-16
      • 2021-08-04
      • 1970-01-01
      相关资源
      最近更新 更多