social
Version:
Multi-platform Social Client for Node
210 lines (185 loc) • 5.99 kB
JavaScript
/**
* The base class for all sns client
* @author Tang Bo Hao
*/
// Module Dependence
var crypto= require('crypto'),
http= require('http'),
https= require('https'),
URL= require('url'),
zlib= require('zlib'),
querystring = require('querystring'),
commonAPIs = require('./apiconfig').commonAPIs;
// export class
var SocialBase = module.exports = function ClientBase(user){
};
SocialBase.prototype.get = function get(api, param, callback) {
callback(new Error('missing implementation of get') );
};
SocialBase.prototype.post = function post(api, body, callback) {
callback(new Error('missing implementation of post') );
};
SocialBase.prototype.filterResponse = function(direct, reqCallback, err, data) {
if(err) return reqCallback(err);
if(direct) return reqCallback( null, data );
if(Array.isArray(data)){ // should be a array
data = data.map(function(item){
return this.geneCommonUser(item);
}, this);
}else{ // should be a object
data = this.geneCommonUser(data);
}
reqCallback(null, data);
};
/**
* Generate user object by server data
* each client should have their own version
* return {Object}
*/
SocialBase.prototype.geneCommonUser = function geneCommonUser( data ) {
return data;
};
// ===! ===== Common SNS API ==========
// generate CommonAPIs function
var apiname, apimethod, cfg, isDirect;
for (var key in commonAPIs) {
apiname = key;
cfg = commonAPIs[key].split("_");
apimethod = cfg[0];
isDirect = cfg[1] === "direct";
SocialBase.prototype[apiname] = (function(name, method, direct){
return function(param, callback){
var api = this.api[name];
if(api)
(this[method])(api, param, this.filterResponse.bind(this, direct, callback ) );
else
callback(new Error("not support api:" + name) );
};
})(apiname, apimethod, isDirect);
};
SocialBase.checkSignature = function(query){
return true;
}
SocialBase.prototype.verify = function (callback) {
callback();
}
// =====!===== Utility functions ============
SocialBase.prototype._createClient= function( port, hostname, method, path, headers, sslEnabled ) {
var options = {
host: hostname,
port: port,
path: path,
method: method,
headers: headers
};
var httpModel;
if( sslEnabled ) {
httpModel= https;
} else {
httpModel= http;
}
return httpModel.request(options);
};
SocialBase.prototype._performSecureRequest= function( method, url, extra_params, post_content_type, callback ) {
if( !post_content_type ) {
post_content_type= "application/x-www-form-urlencoded";
}
var post_body = null;
if(extra_params) {
if( (method == "POST" || method == "PUT") && extra_params != null ) {
post_body= querystring.stringify(extra_params);
} else {
url += (url.indexOf('?') >= 0 ? '&' : '?') + querystring.stringify(extra_params);
}
}
var parsedUrl= URL.parse( url, false );
if( parsedUrl.protocol == "http:" && !parsedUrl.port ) parsedUrl.port= 80;
if( parsedUrl.protocol == "https:" && !parsedUrl.port ) parsedUrl.port= 443;
var headers= {};
headers["Accept"]= "*/*";
headers["Accept-Encoding"]= "gzip";
headers["Connection"]= "close";
headers["User-Agent"]= "Node Server";
headers["Host"]= parsedUrl.host;
headers["Content-Length"]= post_body ? Buffer.byteLength(post_body) : 0;
headers["Content-Type"]= post_content_type;
var path;
if( !parsedUrl.pathname || parsedUrl.pathname == "" ) parsedUrl.pathname ="/";
if( parsedUrl.query ) path= parsedUrl.pathname + "?"+ parsedUrl.query ;
else path= parsedUrl.pathname;
var request;
if( parsedUrl.protocol == "https:" ) {
request= this._createClient(parsedUrl.port, parsedUrl.hostname, method, path, headers, true);
}
else {
request= this._createClient(parsedUrl.port, parsedUrl.hostname, method, path, headers);
}
if( callback ) {
var self = this;
var allowEarlyClose= true;
var callbackCalled= false;
function passBackControl( datastr, dataBuffers, response ) {
if(!callbackCalled) {
callbackCalled= true;
if( dataBuffers ){
datastr = Buffer.concat(dataBuffers).toString();
}
if ( response.statusCode >= 200 && response.statusCode <= 299 ) {
callback(null, datastr, response);
} else {
callback({ statusCode: response.statusCode, data: datastr }, datastr, response);
}
}
}
var onResponse = function ( response) {
var dataBuffers = null;
var datastr = "";
if( response.headers['content-length'] ){
dataBuffers = [];
}
if (response.headers['content-encoding'] == 'gzip') {
var gunzip = zlib.createGunzip();
response.pipe(gunzip);
gunzip.on('data', function (chunk) {
dataBuffers.push( chunk );
});
gunzip.on('end', function () {
passBackControl( null, dataBuffers, response );
});
}else{
response.setEncoding('utf8');
response.on('data', function (chunk) {
if( dataBuffers ){
dataBuffers.push( new Buffer(chunk) );
}else{
datastr += chunk;
}
});
response.on('end', function () {
passBackControl( datastr, dataBuffers, response );
});
}
response.on('close', function () {
if( allowEarlyClose ) {
passBackControl( datastr, dataBuffers, response );
}
});
}
request.on('response', onResponse );
request.on("error", function(err) {
callbackCalled= true;
callback( err )
});
if( (method == "POST" || method =="PUT") && post_body != null && post_body != "" ) {
request.write(post_body);
}
request.end();
}
else {
if( (method == "POST" || method =="PUT") && post_body != null && post_body != "" ) {
request.write(post_body);
}
return request;
}
return;
};