子类化,扩展或包装Node.js'request'模块以增强响应

时间:2015-09-11 04:21:34

标签: node.js node-request

我正在尝试扩展request以劫持和增强其response和其他“身体”参数。最后,我想为我的API添加一些便利方法:

var myRequest = require('./myRequest');
myRequest.get(function(err, hijackedResponse, rows) {
    console.log(hijackedResponse.metadata)
    console.log(rows)
    console.log(rows.first)
});

根据inherits上的节点文档,我认为我可以使其工作(并使用文档中的EventEmitter示例正常工作)。我尝试使用@Tlott的建议让它工作,但意识到对于我的用例它可能不会起作用:

// myRequest.js
var inherits = require('util').inherits;
var Request = require("request").Request;

function MyRequest(options) {
    Request.call(this, options);
}

inherits(MyRequest, Request);

MyRequest.prototype.pet = function() {
    console.log('purr')
}

module.exports = MyRequest;

我也一直在玩extend,希望我能找到一种方法拦截请求的onRequestResponse原型方法,但我正在绘制空白:

var extend = require('extend'),
    request = require("request")

function myResponse() {}

extend(myResponse, request)

// maybe some magic happens here?

module.exports = myResponse

结束于:

var extend = require('extend'),
    Ok = require('objectkit').Ok

function MyResponse(response) {
    var rows = Ok(response.body).getIfExists('rows');
    extend(response, {
        metadata: extend({}, response.body),
        rows: rows
    });
    response.first = (function() {
        return rows[0]
    })();
    response.last = (function() {
        return rows[rows.length - 1] || rows[0]
    })();
    delete response.metadata.rows
    return response;
}

module.exports = MyResponse

请记住,在这个例子中,我作弊并在.get()方法中写了所有内容。在我的最终包装器模块中,我实际上将method作为参数。

1 个答案:

答案 0 :(得分:1)

更新以回答编辑过的问题:

以下是myResponse.js内容的粗略模板。它只实现get()。但是,作为一个简单的骨头,这是一个如何做这种可以完成的演示,我希望它能让你前进。

var request = require('request');

var myRequest = {};

myRequest.get = function (callback) {
    // hardcoding url for demo purposes only
    // could easily get it as a function argument, config option, whatever...
    request.get('http://www.google.com/', function (error, response, body) {
        var rows = [];
        // only checking error here but you might want to check the response code as well
        if (!error) {
            // mess with response here to add metadata. For example...
            response.metadata = 'I am awesome';

            // convert body to rows however you process that. I'm just hardcoding.
            // maybe you'll use JSON.parse() or something.
            rows = ['a', 'b', 'c'];

            // You can add properties to the array if you want.
            rows.first = 'I am first! a a a a';
        }

        // now fire the callback that the user sent you...
        callback(error, response, rows);
    });
};

module.exports = myRequest;

原文回答:

查看the source code for the Request constructor,它需要一个options对象,而该对象又需要一个uri属性。

因此,您需要将此类对象指定为call()中的第二个参数:

Request.call(this, {uri: 'http://localhost/'});

您可能不希望在构造函数中硬编码uri。您可能希望代码看起来更像这样:

function MyRequest(options) {
    Request.call(this, options);
}

...

var myRequest = new MyRequest({uri: 'http://localhost/'});

要使您的代码有效,您还需要将util.inherits()移到MyRequest.prototype.pat()的声明之上。似乎util.inherits()破坏了第一个参数的任何现有原型方法。