00001 var http = require('http')
00002 , https = require('https')
00003 , url = require('url')
00004 , Serializer = require('./serializer')
00005 , Deserializer = require('./deserializer')
00006 , Cookies = require('./cookies')
00007
00008
00025 function Client(options, isSecure) {
00026
00027
00028 if (false === (this instanceof Client)) {
00029 return new Client(options, isSecure)
00030 }
00031
00032
00033 if (typeof options === 'string') {
00034 options = url.parse(options)
00035 options.host = options.hostname
00036 options.path = options.pathname
00037 }
00038
00039 if (typeof options.url !== 'undefined') {
00040 var parsedUrl = url.parse(options.url);
00041 options.host = parsedUrl.hostname;
00042 options.path = parsedUrl.pathname;
00043 options.port = parsedUrl.port;
00044 }
00045
00046
00047 var headers = {
00048 'User-Agent' : 'NodeJS XML-RPC Client'
00049 , 'Content-Type' : 'text/xml'
00050 , 'Accept' : 'text/xml'
00051 , 'Accept-Charset' : 'UTF8'
00052 , 'Connection' : 'Keep-Alive'
00053 }
00054 options.headers = options.headers || {}
00055
00056 if (options.headers.Authorization == null &&
00057 options.basic_auth != null &&
00058 options.basic_auth.user != null &&
00059 options.basic_auth.pass != null)
00060 {
00061 var auth = options.basic_auth.user + ':' + options.basic_auth.pass
00062 options.headers['Authorization'] = 'Basic ' + new Buffer(auth).toString('base64')
00063 }
00064
00065 for (var attribute in headers) {
00066 if (options.headers[attribute] === undefined) {
00067 options.headers[attribute] = headers[attribute]
00068 }
00069 }
00070
00071 options.method = 'POST'
00072 this.options = options
00073
00074 this.isSecure = isSecure
00075 this.headersProcessors = {
00076 processors: [],
00077 composeRequest: function(headers) {
00078 this.processors.forEach(function(p) {p.composeRequest(headers);})
00079 },
00080 parseResponse: function(headers) {
00081 this.processors.forEach(function(p) {p.parseResponse(headers);})
00082 }
00083 };
00084 if (options.cookies) {
00085 this.cookies = new Cookies();
00086 this.headersProcessors.processors.unshift(this.cookies);
00087 }
00088 }
00089
00099 Client.prototype.methodCall = function methodCall(method, params, callback) {
00100 var options = this.options
00101 var xml = Serializer.serializeMethodCall(method, params, options.encoding)
00102 var transport = this.isSecure ? https : http
00103
00104 options.headers['Content-Length'] = Buffer.byteLength(xml, 'utf8')
00105 this.headersProcessors.composeRequest(options.headers)
00106 var request = transport.request(options, function(response) {
00107
00108 var body = []
00109 response.on('data', function (chunk) { body.push(chunk) })
00110
00111 function __enrichError (err) {
00112 Object.defineProperty(err, 'req', { value: request })
00113 Object.defineProperty(err, 'res', { value: response })
00114 Object.defineProperty(err, 'body', { value: body.join('') })
00115 return err
00116 }
00117
00118 if (response.statusCode == 404) {
00119 callback(__enrichError(new Error('Not Found')))
00120 }
00121 else {
00122 this.headersProcessors.parseResponse(response.headers)
00123
00124 var deserializer = new Deserializer(options.responseEncoding)
00125
00126 deserializer.deserializeMethodResponse(response, function(err, result) {
00127 if (err) {
00128 err = __enrichError(err)
00129 }
00130 callback(err, result)
00131 })
00132 }
00133 }.bind(this))
00134
00135 request.on('error', callback)
00136 request.write(xml, 'utf8')
00137 request.end()
00138 }
00139
00147 Client.prototype.getCookie = function getCookie(name) {
00148 if (!this.cookies) {
00149 throw 'Cookies support is not turned on for this client instance';
00150 }
00151 return this.cookies.get(name);
00152 }
00153
00168 Client.prototype.setCookie = function setCookie(name, value) {
00169 if (!this.cookies) {
00170 throw 'Cookies support is not turned on for this client instance';
00171 }
00172 this.cookies.set(name, value);
00173 return this;
00174 }
00175
00176 module.exports = Client
00177