最近我开始学习一些关于Node.js及其功能的内容,并尝试将其用于某些Web服务。 我想创建一个Web服务,它将作为Web请求的代理。 我希望我的服务以这种方式工作:
为了实现它,我使用了以下代码:
app.js:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var proxy = require('./proxy_query.js')
function makeProxyApiRequest(name) {
return proxy.getUserData(name, parseProxyApiRequest);
}
function parseProxyApiRequest(data) {
returned_data = JSON.parse(data);
if (returned_data.error) {
console.log('An eror has occoured. details: ' + JSON.stringify(returned_data));
returned_data = '';
}
return JSON.stringify(returned_data);
}
app.post('/api/getuserinfo/tom', function(request, response) {
makeProxyApiRequest('tom', response);
//response.end(result);
});
var port = 7331;
proxy_query.js:
var https = require('https');
var callback = undefined;
var options = {
host: 'targetsite.com',
port: 443,
method: 'GET',
};
function resultHandlerCallback(result) {
var buffer = '';
result.setEncoding('utf8');
result.on('data', function(chunk){
buffer += chunk;
});
result.on('end', function(){
if (callback) {
callback(buffer);
}
});
}
exports.getUserData = function(name, user_callback) {
callback = user_callback
options['path'] = user + '?name=' + name;
var request = https.get(options, resultHandlerCallback);
request.on('error', function(e){
console.log('error from proxy_query:getUserData: ' + e.message)
});
request.end();
}
app.listen(port);
我希望我没有搞砸这段代码,因为我更换了一些东西以适应我的榜样。
无论如何,问题是我想在HTTP请求完成时将响应发布给用户而我无法找到如何执行此操作,因为我使用express和express使用异步调用,http请求也是如此。 我知道如果我想这样做,我应该将makeProxyApiRequest传递给响应对象,这样他就可以将它传递给回调,但由于asyn问题,这是不可能的。
有什么建议吗? 将不胜感激。
答案 0 :(得分:2)
当您使用函数处理路由处理中的请求时,最好将它们编写为快速中间件函数,获取特定的请求/响应对,并使用express的next
级联模型:< / p>
function makeProxyApiRequest(req, res, next) {
var name = parseProxyApiRequest(req.name);
res.locals.userdata = proxy.getUserData(name);
next();
}
function parseProxyApiRequest(req, res, next) {
try {
// remember that JSON.parse will throw if it fails!
data = JSON.parse(res.locals.userdata);
if (data .error) {
next('An eror has occoured. details: ' + JSON.stringify(data));
}
res.locals.proxyData = data;
next();
}
catch (e) { next("could not parse user data JSON."); }
}
app.post('/api/getuserinfo/tom',
makeProxyApiRequest,
parseProxyApiRequest,
function(req, res) {
// res.write or res.json or res.render or
// something, with this specific request's
// data that we stored in res.locals.proxyData
}
);
现在更好的方法是将这些中间件功能移到自己的文件中,这样你就可以做到:
var middleware = require("./lib/proxy_middleware");
app.post('/api/getuserinfo/tom',
middleware.makeProxyApiRequest,
middleware.parseProxyApiRequest,
function(req, res) {
// res.write or res.json or res.render or
// something, with this specific request's
// data that we stored in res.locals.proxyData
}
);
让您的app.js尽可能小。请注意,客户端的浏览器只会等待快递的响应,这会在res.write
,res.json
或res.render
等使用后发生。在此之前,浏览器和服务器之间的连接只是保持打开状态,所以如果您的中间件调用需要很长时间,那很好 - 浏览器会愉快地等待长时间以获得回复的响应,并将在同一时间做其他事情。
现在,为了得到name
,我们可以使用express的参数构造:
app.param("name", function(req, res, next, value) {
req.params.name = value;
// do something if we need to here, like verify it's a legal name, etc.
// for instance:
var isvalidname = validator.checkValidName(name);
if(!isvalidname) { return next("Username not valid"); }
next();
});
...
app.post("/api/getuserinfo/:name", ..., ..., ...);
使用此系统,将根据我们使用app.param定义的:name
参数来处理任何路线的name
部分。请注意,我们不需要多次定义它:我们可以执行以下操作,它们都可以正常工作:
app.post("/api/getuserinfo/:name", ..., ..., ...);
app.post("/register/:name", ..., ..., ... );
app.get("/api/account/:name", ..., ..., ... );
并且对于具有:name的每个路由,“name”参数处理程序的代码将启动。
对于proxy_query.js
文件,将其重写为适当的模块可能比使用单个导出更安全:
// let's not do more work than we need: http://npmjs.org/package/request
// is way easier than rolling our own URL fetcher. In Node.js the idea is
// to write as little as possible, relying on npmjs.org to find you all
// the components that you need to glue together. If you're writing more
// than just the glue, you're *probably* doing more than you need to.
var request = require("request");
module.exports = {
getURL: function(name, url, callback) {
request.get(url, function(err, result) {
if(err) return callback(err);
// do whatever processing you need to do to result:
var processedResult = ....
callback(false, processedResult);
});
}
};
然后我们可以在中间件中使用proxy = require("./lib/proxy_query");
来实际获取URL数据。