子类化、扩展或包装 Node.js 'request' 模块以增强响应
Subclassing, extending or wrapping Node.js 'request' module to enhance response
我正在尝试扩展 request
以劫持和增强其 response
和其他 'body' 参数。最后,我想为我的 API:
添加一些方便的方法
var myRequest = require('./myRequest');
myRequest.get(function(err, hijackedResponse, rows) {
console.log(hijackedResponse.metadata)
console.log(rows)
console.log(rows.first)
});
根据 inherits
上的 Node 文档,我认为我可以让它工作(并且使用文档中的 EventEmitter
示例工作正常)。我尝试使用@Trott 的建议让它工作,但意识到对于我的用例它可能无法工作:
// 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
作为参数。
已更新以回答编辑后的问题:
这是您 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()
似乎破坏了第一个参数的任何现有原型方法。
我正在尝试扩展 request
以劫持和增强其 response
和其他 'body' 参数。最后,我想为我的 API:
var myRequest = require('./myRequest');
myRequest.get(function(err, hijackedResponse, rows) {
console.log(hijackedResponse.metadata)
console.log(rows)
console.log(rows.first)
});
根据 inherits
上的 Node 文档,我认为我可以让它工作(并且使用文档中的 EventEmitter
示例工作正常)。我尝试使用@Trott 的建议让它工作,但意识到对于我的用例它可能无法工作:
// 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
作为参数。
已更新以回答编辑后的问题:
这是您 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()
似乎破坏了第一个参数的任何现有原型方法。