自己封装的一个http请求,纯分享,无它耳
发布于 5 年前 作者 fantasticsoul 8158 次浏览 最后一次编辑是 4 年前 来自 分享

分享一个自己封装的方法:用nodejs充当客户端向服务器发起http或者https请求,高手请无视啦,哈哈:

/**
 * 提交http or https请求
 * these two examples below is ok!they return a equal result:
 * _commitHttpReq({url:"http://www.baidu.com/s?wd=nba",protocol:"http"},function(err,reply){console.log(reply);});
 * _commitHttpReq({url:"http://www.baidu.com/s",protocol:"http",data:{wd:"nba"}},function(err,reply){console.log(reply);});
 * @param opt
 * {    host:'192.168.1.16'
 *      port: '8001' //可不填,默认为80端口
 *      path: '/someService' //或者不填写host path两个属性,直接填写url属性,值为:'http://mis.migc.xiaomi.com/api/biz/service/verifySession.do'
 *      method: 'post'
 * }
 * @param data 提交的数据,只支持一层结构的json对象(如{id:3,name:"ss"}),多层的话会出错,url的get请求不支持传多层结构的json对象(如{id:3,name:{first:"a",last:"b"}})
 * @param protocol :http | https
 * @param cb
 */
 function _commitHttpReq(opt,cb) {
	var url=require('url'),querystring = require('querystring');
	function _wrapUrl(opt){
		var err=null;
		if(opt.url){
			var opt_protocol=opt.protocol;
			var sub_protocol=opt.url.substr(0,5);
			if(sub_protocol=="http:"){
				if(opt_protocol){
					if(opt_protocol!="http")err="url's protocol:http not equal option's protocol:"+opt_protocol;
				}else{
					opt.protocol="http";
				}
			}else if(protocol=="https"){
				if(opt_protocol){
					if(opt_protocol!="https")err="url's protocol:http not equal option's protocol:"+opt_protocol;
				}else{
					opt.protocol="https";
				}
			}else if(sub_protocol.indexOf("www")!=-1){
				if(!opt_protocol)err="no protocol defined!";else opt.url=opt_protocol+"://"+opt.url;
			}else{
				err="url writing is invalid";
			}
		}
		return err;
	}
	var out_err=_wrapUrl(opt);
	if(out_err)return cb(out_err,null);
	var protocol=opt.protocol;
	var httpMgr = protocol == "http" ? require('http') : require('https');

	//if opt.url like:"https://www.beyourboss.com/call%s.do?cmd=start&st=%s"
	//var util = require('util');
	//var _regUrl = util.format(opt.url, 'param1', 'param2');//替换掉两个%s占位符

	var method=opt.method?opt.method:'get';
	var port=opt.port?opt.port:80;
	var params = '';
	if(opt.data)params+=querystring.stringify(opt.data);
	if(opt.url){
		if(method=="get" && params.length>0){
			opt.url+=("?"+params);
		}
		var options = url.parse(opt.url);
		options.method = method;
		options.port = port;
		//console.log("url:"+opt.url);
	}else{
		var options = {
			host: opt.host,
			port: port,
			path: opt.path,//形如:"/callSomething.do"
			method: method
		};
	}
	//console.log(params);
	options.headers = {
		'Content-Type': 'application/x-www-form-urlencoded',
		'Content-Length' : params.length
	};
	//if need cookie,example: options.headers.cookie='a=b;c=d;',
	var req = httpMgr.request(options, function (res) {
		console.log('STATUS: ' + res.statusCode);
		//console.log(res);
		console.log('HEADERS: ' + JSON.stringify(res.headers));
		res.setEncoding('utf8');//设置字符编码
		var _data="";//返回数据流
		res.on('data', function (chunk) {//数据
			_data+=chunk;
		});
		// 结束回调
		res.on('end', function(){
			cb(null,_data);
		});
		req.on('error', function(e) {
			cb(err,null);
		});
	});
	req.write(params);
	req.end();
};

//以下测试请解开在运行,都是相同的效果啦^_^
//_commitHttpReq({url:"http://www.baidu.com/s?wd=nba",protocol:"http"},function(err,reply){console.log(reply);});
//_commitHttpReq({url:"http://www.baidu.com/s?wd=nba"},function(err,reply){console.log(reply);});
//_commitHttpReq({url:"www.baidu.com/s?wd=nba",protocol:"http"},function(err,reply){console.log(reply);});
//_commitHttpReq({url:"http://www.baidu.com/s",protocol:"http",data:{wd:"nba"}},function(err,reply){console.log(reply);});
//_commitHttpReq({url:"http://www.baidu.com/s",protocol:"http",data:{wd:"nba"},method:"get"},function(err,reply){console.log(reply);});

//如果是手机游戏发起http请求,通常后端开发自己写完接口后,调用一下:【这一段仅仅是demo,解开也没用哦,嘿嘿】
//_commitHttpReq({
//	host: "192.168.1.126",
//	port: 2000,
//	protocol: "http",
//	path: "/callMethod.do",
//	method: "post",
//	data: {to_server: JSON.stringify({uid:11,x:22,y:33,soldiers:["s1","s3"]})}
//}, function (err, reply) {
//	console.log(err);
//	console.log(reply);
//});
12 回复

感谢分享,有点笔误 else if(protocol==“https”){ 应该是else if(sub_protocol==“https”){

赞勇气,还是建议别自己写

@fengmk2 有类似的模块可以推荐吗?

@FireTercel request 和 superagent 都可以

来自酷炫的 CNodeMD

var _data="";//返回数据流
		res.on('data', function (chunk) {//数据
			_data+=chunk;
		});

来来来 让@JacksonTian 来教训教训你 …

@cctv1005s 是的,我现在用request库,方便多了,不用require(‘http’).request(),回调里一堆on,好处仅仅是了解如果使用node提供的原生库发起一个http客户端的请求而已

@FireTercel 是的,谢谢指点,其实我现在都用request库了哈哈,

@fantasticsoul

chunk 是 Buffer, _data += chunk, 相当于 _data += chunk.toString() 直接当 utf8 toString 了, 碰上 chunk 是 gb2312 / gbk 等编码的直接锟斤拷 买本深入浅出Node.js吧, 里面有

我在想,两年没动的帖子为啥出现在了timeline里…

回到顶部