在nodejs一次请求中,需要以client方式多次和不同的host交互数据,我采用了http.request()遇到问题。
发布于 12 年前 作者 mackjoner 13009 次浏览 最后一次编辑是 8 年前

如题:
在nodejs一次请求中,需要一client方式多次和不同的host交互数据,我采用了http.request()遇到问题。第一次clienthttp请求可以响应回数据,接着拿数据做第二次请求,数据交互就出现影响了。
基本实现逻辑是:
在nodejs的routes上调用一个service,这个service拿到route传过来的请求参数,然后发起http.request()请求,在callback里判定数据,合法接着用http.request()响应的数据继续发起http.request()请求,这个时候的host已经不同,问题出来了。在sockets上有两个host值,第一次成功的请求host也在里面了,然后这次的数据交互就失败了。
我单独做不同host的http.request()数据交互是正确的。
下面是console.log()信息,有没有办法在第二次发起http.request()的时候,没有第一次host缓存,不能单独做两次nodejs的请求来分离这个逻辑。

{ host: '192.168.1.249',
  port: 80,
  path: '/yy.action',
  method: 'POST',
  headers: { 'Content-Type': 'text/xml; charset=UTF-8' } }
{ output: [],
  outputEncodings: [],
  writable: true,
  _last: false,
  chunkedEncoding: false,
  shouldKeepAlive: true,
  useChunkedEncodingByDefault: true,
  _hasBody: true,
  _trailer: '',
  finished: false,
  agent: 
   { options: {},
     requests: {},
     sockets: 
      { '192.168.1.105:8080': [Object],
        '192.168.1.249:80': [Object] },
     maxSockets: 5,
     _events: { free: [Function] },
     createConnection: [Function] },
  socketPath: undefined,
  method: 'POST',
  path: '/yy.action',
  _events: 
   { response: { [Function: g] listener: [Function] },
     socket: { [Function: g] listener: [Function] } },
  _headers: 
   { 'content-type': 'text/xml; charset=UTF-8',
     host: '192.168.1.249' },
  _headerNames: { 'content-type': 'Content-Type', host: 'Host' } }
8 回复
request.on("socket", function(socket) {
   socket.emit("agentRemove");
});

再怎么做,浏览器也是不会允许你轻易的突破域名搞XSS的。涉及到跨域,就需要特别处理了。

楼主可以试试加上 origins = “*”之类的配置,让浏览器知道你的Access-Control-Allow-Origin

我不知道我是不是理解了楼主的意思:用Node.js架设Http服务,客户那里有请求过来后,你生成一个变量client,然后访问其他地址a,如果成功,继续用此变量访问其他地址b?

我不知道我是不是理解了楼主的意思:用Node.js架设Http服务,客户那里有请求过来后,你生成一个变量client,然后访问其他地址a,如果成功,继续用此变量访问其他地址b?

var config = require('../config').config;
var product = require('../models/product');
var dateTimeFormat = require('../libs/dateTimeFormat');
var buffertools = require(config.node_modules + 'buffertools');
var libxmljs = require(config.node_modules + 'libxmljs');

exports.add = function(req, res) {
	var method = req.method.toLowerCase();
	if (method == 'get') {
		res.render('addprop', {
			title: 'AddProp'
		})
	}
	if (method == 'post') {

		product.saveProduct(req.body['PropName'], req.body['PropDesc'], req.body['PropPrice']);

		res.writeHead(200, {
			'Content-Type': 'text/plain'
		});
		res.end('success\n');
	}

};

exports.generateOrder = function(req, res) {
	var method = req.method.toLowerCase();

	require('util').log('msg: ========== Request Start =========');

	var _req = req;
	var _res = res;

	var _payType = '';
	var _propId = '';

	if (method == 'get') {
		_payType = req.query['payment_channel'];
		_propId = req.query['product_id'];
	} else if (method == 'post') {
		_payType = req.body['payment_channel'];
		_propId = req.body['product_id'];
	} else {
		return;
	}

	var _payAmout = null;

	_payAmout = product.getProductPriceById(_propId);
	if (_payAmout != null) {
		require('util').log(_payAmout);

		var _payOrderTime = new Date();
		_payOrderTime = dateTimeFormat.formatDate(_payOrderTime, 'yyyyMMddhhmmss');
		var _rand = rand(5);
		var _payOrderId = _payOrderTime + _rand;
		var _payOrderDesc = '商品名称';
		var _payTransTimeOut = new Date();
		_payTransTimeOut.setDate(_payTransTimeOut.getDate() + 1);
		_payTransTimeOut = dateTimeFormat.formatDate(_payTransTimeOut, 'yyyyMMddhhmmss');

		var _remoteSign = '';

		_remoteSign = remoteSignToString(_payOrderId, _payOrderTime, _payAmout, _payOrderDesc, _payTransTimeOut);


		require('util').log(_remoteSign);

		var _sign = '';
		var _payxml = '';
		var _resxml = '';
		var _xmlObj = null;
		var _respCode = '';
		var _respDesc = '';
		var _clientRemoteSign = '';
		var _resClientData = '';
		var _jsonObj = null;

		postSign(_remoteSign, function(chunk) {
			_sign = '' + decodeURIComponent(chunk);
			require('util').log(_sign);
			_payxml = createPayXmlInfo(_sign, _payOrderId, _payOrderTime, _payAmout, _payOrderDesc, _payTransTimeOut);
			require('util').log(_payxml);

			postOrder(_payxml, function(chunk) {
				_resxml = '' + decodeURIComponent(chunk.replace(/(\+)/g, " "));
				require('util').log(_resxml);
				_xmlObj = libxmljs.parseXmlString(_resxml);
				_respCode = _xmlObj.get('//respCode').text();
				_respDesc = _xmlObj.get('//respDesc').text();
				if (_respCode == '0000') {
					product.saveOrder(_payOrderId, _payType, _payAmout);
					
					_clientRemoteSign = clientRemoteSignToString(_payOrderId, _payOrderTime);
					postSign(_clientRemoteSign, function(chunk) {
						_sign = '' + decodeURIComponent(chunk);
						_resClientData = createClientPayXmlInfo(_sign, _payOrderId, _payOrderTime);

						_jsonObj = {
							payment_channel: _payType,
							order_id: _payOrderId,
							order_data: _resClientData
						};
						resJsonObj(res, _jsonObj);
					});

				}

			})

		});
	}

}

function remoteSignToString(orderid, paytime, price, paydesc, paytimeout) {

	var signStr = new Buffer('xxx');
	//signStr = buffertools.concat(signStr, 'xxx');
	signStr = signStr.toString();

	return signStr;
}

function clientRemoteSignToString(orderid, paytime) {
	var clientSignStr = new Buffer('xxx');
	//clientSignStr = buffertools.concat(clientSignStr, 'xxx');
	clientSignStr = clientSignStr.toString();

	return clientSignStr;
}

function createPayXmlInfo(sign, orderid, paytime, price, paydesc, paytimeout) {

	var xmlBody = new Buffer('<?xml version=\"1.0\" encoding=\"utf-8\"?>');
	//...
	xmlBody = xmlBody.toString();

	return xmlBody;
}

function createClientPayXmlInfo(sign, orderid, paytime) {

	var xmlBody = new Buffer('<?xml version=\"1.0\" encoding=\"UTF-8\"?>');
	//...
	xmlBody = xmlBody.toString('base64');

	return xmlBody;

}

function rand(n) {
	var num = '';

	for (i = 0; i < n; i++) {
		num += Math.floor(Math.random() * 10);
	}

	return num;
}

function postSign(str, callback) {
	var http = require('http');

	
	var toSign = '' + encodeURIComponent(str);
	var post_data = require('querystring').stringify({
		
	});

	var post_options = {
		host: 'www.domain.org',
		port: 8080,
		path: '/xxx',
		method: 'POST',
		headers: {
			'Content-Type': 'application/x-www-form-urlencoded',
			'Content-Length': post_data.length
		}
	};
	var post_req = http.request(post_options, function(res) {
		require('util').log('STATUS: ' + res.statusCode);
		require('util').log('HEADERS: ' + JSON.stringify(res.headers));
		res.setEncoding('utf8');
		res.on('data', function(chunk) {
			callback(chunk);
		});
	});
	post_req.write(post_data);
	post_req.end();
}

function postOrder(str, callback) {
	var http = require('http');

	var post_data = '' + encodeURIComponent(str);

	var post_options = {
		host: 'www.domain1.com',
		port: 80,
		path: '/xxx',
		method: 'POST',
		headers: {
			'Content-Type': 'text/xml; charset=UTF-8'
		}

	};
	var post_req = http.request(post_options, function(res) {
		require('util').log('STATUS: ' + res.statusCode);
		require('util').log('HEADERS: ' + JSON.stringify(res.headers));
		res.setEncoding('utf8');
		res.on('data', function(chunk) {
			callback(chunk);
		});
	});
	post_req.write(post_data);
	post_req.end();
}

function resJsonObj(res, str) {

	res.writeHead(200, {
		'Content-Type': 'application/json'
	});
	res.end(JSON.stringify(str));
	require('util').log('msg: ========== Request End =========');

}

@olddog app.get(’/payment/order/add’, product.generateOrder); 就是我的具体逻辑了,现在发现是express引起的,因为我不用这个express做routes就没有问题,求各大高手切磋。

发现是forever的造出的影响, 在进程没达到return的时候,就被forever把进程重启了。 直接node app.js 测试没有问题。

回到顶部