Initial commit
This commit is contained in:
14
node_modules/jayson/lib/client/browser/index.d.ts
generated
vendored
Normal file
14
node_modules/jayson/lib/client/browser/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import * as jayson from '../../..';
|
||||
|
||||
type ClientBrowserCallServerFunctionCallback = (err?:Error | null, response?:string) => void;
|
||||
|
||||
type ClientBrowserCallServerFunction = (request:string, callback:ClientBrowserCallServerFunctionCallback) => void;
|
||||
|
||||
declare class ClientBrowser {
|
||||
constructor(callServer:ClientBrowserCallServerFunction, options:jayson.ClientOptions);
|
||||
request(method: string, params: jayson.RequestParamsLike, id?: string | null, callback?: jayson.JSONRPCCallbackType): jayson.JSONRPCRequest;
|
||||
request(method: string, params: jayson.RequestParamsLike, callback?: jayson.JSONRPCCallbackType): jayson.JSONRPCRequest;
|
||||
request(method: Array<jayson.JSONRPCRequestLike>, callback: jayson.JSONRPCCallbackTypeBatch): Array<jayson.JSONRPCRequest>;
|
||||
}
|
||||
|
||||
export = ClientBrowser;
|
||||
163
node_modules/jayson/lib/client/browser/index.js
generated
vendored
Normal file
163
node_modules/jayson/lib/client/browser/index.js
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
'use strict';
|
||||
|
||||
const uuid = require('uuid').v4;
|
||||
const generateRequest = require('../../generateRequest');
|
||||
|
||||
/**
|
||||
* Constructor for a Jayson Browser Client that does not depend any node.js core libraries
|
||||
* @class ClientBrowser
|
||||
* @param {Function} callServer Method that calls the server, receives the stringified request and a regular node-style callback
|
||||
* @param {Object} [options]
|
||||
* @param {Function} [options.reviver] Reviver function for JSON
|
||||
* @param {Function} [options.replacer] Replacer function for JSON
|
||||
* @param {Number} [options.version=2] JSON-RPC version to use (1|2)
|
||||
* @param {Function} [options.generator] Function to use for generating request IDs
|
||||
* @param {Boolean} [options.notificationIdNull=false] When true, version 2 requests will set id to null instead of omitting it
|
||||
* @return {ClientBrowser}
|
||||
*/
|
||||
const ClientBrowser = function(callServer, options) {
|
||||
if(!(this instanceof ClientBrowser)) {
|
||||
return new ClientBrowser(callServer, options);
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
this.options = {
|
||||
reviver: typeof options.reviver !== 'undefined' ? options.reviver : null,
|
||||
replacer: typeof options.replacer !== 'undefined' ? options.replacer : null,
|
||||
generator: typeof options.generator !== 'undefined' ? options.generator : function() { return uuid(); },
|
||||
version: typeof options.version !== 'undefined' ? options.version : 2,
|
||||
notificationIdNull: typeof options.notificationIdNull === 'boolean' ? options.notificationIdNull : false,
|
||||
};
|
||||
|
||||
this.callServer = callServer;
|
||||
};
|
||||
|
||||
module.exports = ClientBrowser;
|
||||
|
||||
/**
|
||||
* Creates a request and dispatches it if given a callback.
|
||||
* @param {String|Array} method A batch request if passed an Array, or a method name if passed a String
|
||||
* @param {Array|Object} [params] Parameters for the method
|
||||
* @param {String|Number} [id] Optional id. If undefined an id will be generated. If null it creates a notification request
|
||||
* @param {Function} [callback] Request callback. If specified, executes the request rather than only returning it.
|
||||
* @throws {TypeError} Invalid parameters
|
||||
* @return {Object} JSON-RPC 1.0 or 2.0 compatible request
|
||||
*/
|
||||
ClientBrowser.prototype.request = function(method, params, id, callback) {
|
||||
const self = this;
|
||||
let request = null;
|
||||
|
||||
// is this a batch request?
|
||||
const isBatch = Array.isArray(method) && typeof params === 'function';
|
||||
|
||||
if (this.options.version === 1 && isBatch) {
|
||||
throw new TypeError('JSON-RPC 1.0 does not support batching');
|
||||
}
|
||||
|
||||
// is this a raw request?
|
||||
const isRaw = !isBatch && method && typeof method === 'object' && typeof params === 'function';
|
||||
|
||||
if(isBatch || isRaw) {
|
||||
callback = params;
|
||||
request = method;
|
||||
} else {
|
||||
if(typeof id === 'function') {
|
||||
callback = id;
|
||||
// specifically undefined because "null" is a notification request
|
||||
id = undefined;
|
||||
}
|
||||
|
||||
const hasCallback = typeof callback === 'function';
|
||||
|
||||
try {
|
||||
request = generateRequest(method, params, id, {
|
||||
generator: this.options.generator,
|
||||
version: this.options.version,
|
||||
notificationIdNull: this.options.notificationIdNull,
|
||||
});
|
||||
} catch(err) {
|
||||
if(hasCallback) {
|
||||
return callback(err);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
// no callback means we should just return a raw request
|
||||
if(!hasCallback) {
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let message;
|
||||
try {
|
||||
message = JSON.stringify(request, this.options.replacer);
|
||||
} catch(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
this.callServer(message, function(err, response) {
|
||||
self._parseResponse(err, response, callback);
|
||||
});
|
||||
|
||||
// always return the raw request
|
||||
return request;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses a response from a server
|
||||
* @param {Object} err Error to pass on that is unrelated to the actual response
|
||||
* @param {String} responseText JSON-RPC 1.0 or 2.0 response
|
||||
* @param {Function} callback Callback that will receive different arguments depending on the amount of parameters
|
||||
* @private
|
||||
*/
|
||||
ClientBrowser.prototype._parseResponse = function(err, responseText, callback) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!responseText) {
|
||||
// empty response text, assume that is correct because it could be a
|
||||
// notification which jayson does not give any body for
|
||||
return callback();
|
||||
}
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = JSON.parse(responseText, this.options.reviver);
|
||||
} catch(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if(callback.length === 3) {
|
||||
// if callback length is 3, we split callback arguments on error and response
|
||||
|
||||
// is batch response?
|
||||
if(Array.isArray(response)) {
|
||||
|
||||
// neccesary to split strictly on validity according to spec here
|
||||
const isError = function(res) {
|
||||
return typeof res.error !== 'undefined';
|
||||
};
|
||||
|
||||
const isNotError = function (res) {
|
||||
return !isError(res);
|
||||
};
|
||||
|
||||
return callback(null, response.filter(isError), response.filter(isNotError));
|
||||
|
||||
} else {
|
||||
|
||||
// split regardless of validity
|
||||
return callback(null, response.error, response.result);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
callback(null, response);
|
||||
};
|
||||
116
node_modules/jayson/lib/client/http.js
generated
vendored
Normal file
116
node_modules/jayson/lib/client/http.js
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
'use strict';
|
||||
|
||||
const http = require('http');
|
||||
const url = require('url');
|
||||
const utils = require('../utils');
|
||||
const Client = require('../client');
|
||||
const { version } = require('../../package.json');
|
||||
|
||||
/**
|
||||
* Constructor for a Jayson HTTP Client
|
||||
* @class ClientHttp
|
||||
* @constructor
|
||||
* @extends Client
|
||||
* @param {Object|String} [options] String interpreted as a URL
|
||||
* @param {String} [options.encoding="utf8"] Encoding to use
|
||||
* @return {ClientHttp}
|
||||
*/
|
||||
const ClientHttp = function(options) {
|
||||
// accept first parameter as a url string
|
||||
if(typeof(options) === 'string') {
|
||||
options = url.parse(options);
|
||||
}
|
||||
|
||||
if(!(this instanceof ClientHttp)) {
|
||||
return new ClientHttp(options);
|
||||
}
|
||||
Client.call(this, options);
|
||||
|
||||
const defaults = utils.merge(this.options, {
|
||||
encoding: 'utf8'
|
||||
});
|
||||
|
||||
this.options = utils.merge(defaults, options || {});
|
||||
};
|
||||
require('util').inherits(ClientHttp, Client);
|
||||
|
||||
module.exports = ClientHttp;
|
||||
|
||||
ClientHttp.prototype._request = function(request, callback) {
|
||||
const self = this;
|
||||
// copies options so object can be modified in this context
|
||||
const options = utils.merge({}, this.options);
|
||||
|
||||
utils.JSON.stringify(request, options, function(err, body) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
options.method = options.method || 'POST';
|
||||
|
||||
const headers = {
|
||||
'Content-Length': Buffer.byteLength(body, options.encoding),
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
Accept: 'application/json',
|
||||
'User-Agent': `jayson-${version}`,
|
||||
};
|
||||
|
||||
// let user override the headers
|
||||
options.headers = utils.merge(headers, options.headers || {});
|
||||
|
||||
const req = self._getRequestStream(options);
|
||||
|
||||
self.emit('http request', req);
|
||||
|
||||
req.on('response', function(res) {
|
||||
self.emit('http response', res, req);
|
||||
|
||||
res.setEncoding(options.encoding);
|
||||
|
||||
let data = '';
|
||||
res.on('data', function(chunk) { data += chunk; });
|
||||
|
||||
res.on('end', function() {
|
||||
|
||||
// assume we have an error
|
||||
if(res.statusCode < 200 || res.statusCode >= 300) {
|
||||
// assume the server gave the reason in the body
|
||||
const err = new Error(data);
|
||||
err.code = res.statusCode;
|
||||
callback(err);
|
||||
} else {
|
||||
// empty reply
|
||||
if(!data || typeof(data) !== 'string') {
|
||||
return callback();
|
||||
}
|
||||
utils.JSON.parse(data, options, callback);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// abort on timeout
|
||||
req.on('timeout', function() {
|
||||
req.abort(); // req.abort causes "error" event
|
||||
});
|
||||
|
||||
// abort on error
|
||||
req.on('error', function(err) {
|
||||
self.emit('http error', err);
|
||||
callback(err);
|
||||
req.abort();
|
||||
});
|
||||
|
||||
req.end(body);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a stream interface to a http server
|
||||
* @param {Object} options An options object
|
||||
* @return {require('http').ClientRequest}
|
||||
* @private
|
||||
*/
|
||||
ClientHttp.prototype._getRequestStream = function(options) {
|
||||
return http.request(options || {});
|
||||
};
|
||||
34
node_modules/jayson/lib/client/https.js
generated
vendored
Normal file
34
node_modules/jayson/lib/client/https.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
'use strict';
|
||||
|
||||
const https = require('https');
|
||||
const ClientHttp = require('./http');
|
||||
|
||||
/**
|
||||
* Constructor for a Jayson HTTPS Client
|
||||
* @class ClientHttps
|
||||
* @constructor
|
||||
* @extends ClientHttp
|
||||
* @param {Object|String} [options] String interpreted as a URL
|
||||
* @param {String} [options.encoding="utf8"] Encoding to use
|
||||
* @return {ClientHttps}
|
||||
*/
|
||||
const ClientHttps = function(options) {
|
||||
if(!(this instanceof ClientHttps)) {
|
||||
return new ClientHttps(options);
|
||||
}
|
||||
// just proxy to constructor for ClientHttp
|
||||
ClientHttp.call(this, options);
|
||||
};
|
||||
require('util').inherits(ClientHttps, ClientHttp);
|
||||
|
||||
module.exports = ClientHttps;
|
||||
|
||||
/**
|
||||
* Gets a stream interface to a https server
|
||||
* @param {Object} options An options object
|
||||
* @return {require('https').ClientRequest}
|
||||
* @private
|
||||
*/
|
||||
ClientHttps.prototype._getRequestStream = function(options) {
|
||||
return https.request(options || {});
|
||||
};
|
||||
220
node_modules/jayson/lib/client/index.js
generated
vendored
Normal file
220
node_modules/jayson/lib/client/index.js
generated
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
'use strict';
|
||||
|
||||
const events = require('events');
|
||||
const utils = require('../utils');
|
||||
|
||||
/**
|
||||
* Constructor for a Jayson Client
|
||||
* @class Client
|
||||
* @extends require('events').EventEmitter
|
||||
* @param {Server} [server] An instance of Server (a object with a "call" method")
|
||||
* @param {Object} [options]
|
||||
* @param {Function} [options.reviver] Reviver function for JSON
|
||||
* @param {Function} [options.replacer] Replacer function for JSON
|
||||
* @param {Number} [options.version=2] JSON-RPC version to use (1|2)
|
||||
* @param {Boolean} [options.notificationIdNull=false] When true, version 2 requests will set id to null instead of omitting it
|
||||
* @param {Function} [options.generator] Function to use for generating request IDs
|
||||
* @return {Client}
|
||||
*/
|
||||
const Client = function(server, options) {
|
||||
if(arguments.length === 1 && utils.isPlainObject(server)) {
|
||||
options = server;
|
||||
server = null;
|
||||
}
|
||||
|
||||
if(!(this instanceof Client)) {
|
||||
return new Client(server, options);
|
||||
}
|
||||
|
||||
const defaults = {
|
||||
reviver: null,
|
||||
replacer: null,
|
||||
generator: utils.generateId,
|
||||
version: 2,
|
||||
notificationIdNull: false,
|
||||
};
|
||||
|
||||
this.options = utils.merge(defaults, options || {});
|
||||
|
||||
if(server) {
|
||||
this.server = server;
|
||||
}
|
||||
};
|
||||
require('util').inherits(Client, events.EventEmitter);
|
||||
|
||||
module.exports = Client;
|
||||
|
||||
/**
|
||||
* HTTP client constructor
|
||||
* @type ClientHttp
|
||||
* @static
|
||||
*/
|
||||
Client.http = require('./http');
|
||||
|
||||
/**
|
||||
* HTTPS client constructor
|
||||
* @type ClientHttps
|
||||
* @static
|
||||
*/
|
||||
Client.https = require('./https');
|
||||
|
||||
/**
|
||||
* TCP client constructor
|
||||
* @type ClientTcp
|
||||
* @static
|
||||
*/
|
||||
Client.tcp = require('./tcp');
|
||||
|
||||
/**
|
||||
* TLS client constructor
|
||||
* @type ClientTls
|
||||
* @static
|
||||
*/
|
||||
Client.tls = require('./tls');
|
||||
|
||||
/**
|
||||
* Browser client constructor
|
||||
* @type ClientBrowser
|
||||
* @static
|
||||
*/
|
||||
Client.browser = require('./browser');
|
||||
|
||||
/**
|
||||
* Websocket client constructor
|
||||
* @type ClientWebsocket
|
||||
* @static
|
||||
*/
|
||||
Client.websocket = require('./websocket');
|
||||
|
||||
/**
|
||||
* Creates a request and dispatches it if given a callback.
|
||||
* @param {String|Array} method A batch request if passed an Array, or a method name if passed a String
|
||||
* @param {Array|Object} params Parameters for the method
|
||||
* @param {String|Number} [id] Optional id. If undefined an id will be generated. If null it creates a notification request
|
||||
* @param {Function} [callback] Request callback. If specified, executes the request rather than only returning it.
|
||||
* @throws {TypeError} Invalid parameters
|
||||
* @return {Object} JSON-RPC 1.0 or 2.0 compatible request
|
||||
*/
|
||||
Client.prototype.request = function(method, params, id, callback) {
|
||||
const self = this;
|
||||
let request = null;
|
||||
|
||||
// is this a batch request?
|
||||
const isBatch = Array.isArray(method) && typeof(params) === 'function';
|
||||
|
||||
if (this.options.version === 1 && isBatch) {
|
||||
throw new TypeError('JSON-RPC 1.0 does not support batching');
|
||||
}
|
||||
|
||||
// is this a raw request?
|
||||
const isRaw = !isBatch && method && typeof(method) === 'object' && typeof(params) === 'function';
|
||||
|
||||
if(isBatch || isRaw) {
|
||||
callback = params;
|
||||
request = method;
|
||||
} else {
|
||||
if(typeof(id) === 'function') {
|
||||
callback = id;
|
||||
// specifically undefined because "null" is a notification request
|
||||
id = undefined;
|
||||
}
|
||||
|
||||
const hasCallback = typeof(callback) === 'function';
|
||||
|
||||
try {
|
||||
request = utils.request(method, params, id, {
|
||||
generator: this.options.generator,
|
||||
version: this.options.version,
|
||||
notificationIdNull: this.options.notificationIdNull,
|
||||
});
|
||||
} catch(err) {
|
||||
if(hasCallback) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
// no callback means we should just return a raw request before sending
|
||||
if(!hasCallback) {
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.emit('request', request);
|
||||
|
||||
this._request(request, function(err, response) {
|
||||
self.emit('response', request, response);
|
||||
self._parseResponse(err, response, callback);
|
||||
});
|
||||
|
||||
// always return the raw request
|
||||
return request;
|
||||
};
|
||||
|
||||
/**
|
||||
* Executes a request on a directly bound server
|
||||
* @param {Object} request A JSON-RPC 1.0 or 2.0 request
|
||||
* @param {Function} callback Request callback that will receive the server response as the second argument
|
||||
* @private
|
||||
*/
|
||||
Client.prototype._request = function(request, callback) {
|
||||
const self = this;
|
||||
|
||||
// serializes the request as a JSON string so that we get a copy and can run the replacer as intended
|
||||
utils.JSON.stringify(request, this.options, function(err, message) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
self.server.call(message, function(error, success) {
|
||||
const response = error || success;
|
||||
callback(null, response);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses a response from a server, taking care of sugaring
|
||||
* @param {Object} err Error to pass on that is unrelated to the actual response
|
||||
* @param {Object} response JSON-RPC 1.0 or 2.0 response
|
||||
* @param {Function} callback Callback that will receive different arguments depending on the amount of parameters
|
||||
* @private
|
||||
*/
|
||||
Client.prototype._parseResponse = function(err, response, callback) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if(!response || typeof(response) !== 'object') {
|
||||
return callback();
|
||||
}
|
||||
|
||||
if(callback.length === 3) {
|
||||
// if callback length is 3, we split callback arguments on error and response
|
||||
|
||||
// is batch response?
|
||||
if(Array.isArray(response)) {
|
||||
|
||||
// neccesary to split strictly on validity according to spec here
|
||||
const isError = function(res) { return typeof(res.error) !== 'undefined'; };
|
||||
const isNotError = function(res) { return !isError(res); };
|
||||
|
||||
return callback(null, response.filter(isError), response.filter(isNotError));
|
||||
|
||||
} else {
|
||||
|
||||
// split regardless of validity
|
||||
return callback(null, response.error, response.result);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return callback(null, response);
|
||||
|
||||
};
|
||||
90
node_modules/jayson/lib/client/tcp.js
generated
vendored
Normal file
90
node_modules/jayson/lib/client/tcp.js
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
'use strict';
|
||||
|
||||
const net = require('net');
|
||||
const utils = require('../utils');
|
||||
const Client = require('../client');
|
||||
|
||||
/**
|
||||
* Constructor for a Jayson TCP Client
|
||||
* @class ClientTcp
|
||||
* @constructor
|
||||
* @extends Client
|
||||
* @param {Object|String} [options] Object goes into options for net.connect, String goes into options.path. String option argument is NOT recommended.
|
||||
* @return {ClientTcp}
|
||||
*/
|
||||
const ClientTcp = function(options) {
|
||||
if(typeof(options) === 'string') {
|
||||
options = {path: options};
|
||||
}
|
||||
|
||||
if(!(this instanceof ClientTcp)) {
|
||||
return new ClientTcp(options);
|
||||
}
|
||||
Client.call(this, options);
|
||||
|
||||
const defaults = utils.merge(this.options, {
|
||||
encoding: 'utf8'
|
||||
});
|
||||
|
||||
this.options = utils.merge(defaults, options || {});
|
||||
};
|
||||
require('util').inherits(ClientTcp, Client);
|
||||
|
||||
module.exports = ClientTcp;
|
||||
|
||||
ClientTcp.prototype._request = function(request, callback) {
|
||||
const self = this;
|
||||
|
||||
// copies options so object can be modified in this context
|
||||
const options = utils.merge({}, this.options);
|
||||
const delimiter = options.delimiter || '\n';
|
||||
|
||||
utils.JSON.stringify(request, options, function(err, body) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
let handled = false;
|
||||
|
||||
const conn = net.connect(options, function() {
|
||||
|
||||
conn.setEncoding(options.encoding);
|
||||
|
||||
// wont get anything for notifications, just end here
|
||||
if(utils.Request.isNotification(request)) {
|
||||
|
||||
handled = true;
|
||||
conn.end(body + delimiter);
|
||||
callback();
|
||||
|
||||
} else {
|
||||
|
||||
utils.parseStream(conn, options, function(err, response) {
|
||||
handled = true;
|
||||
conn.end();
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
callback(null, response);
|
||||
});
|
||||
|
||||
conn.write(body + delimiter);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
self.emit('tcp socket', conn);
|
||||
|
||||
conn.on('error', function(err) {
|
||||
self.emit('tcp error', err);
|
||||
callback(err);
|
||||
});
|
||||
|
||||
conn.on('end', function() {
|
||||
if(!handled) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
89
node_modules/jayson/lib/client/tls.js
generated
vendored
Normal file
89
node_modules/jayson/lib/client/tls.js
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
'use strict';
|
||||
|
||||
const tls = require('tls');
|
||||
const utils = require('../utils');
|
||||
const Client = require('../client');
|
||||
|
||||
/**
|
||||
* Constructor for a Jayson TLS-encrypted TCP Client
|
||||
* @class ClientTls
|
||||
* @constructor
|
||||
* @extends Client
|
||||
* @param {Object|String} [options] Object goes into options for tls.connect, String goes into options.path. String option argument is NOT recommended.
|
||||
* @return {ClientTls}
|
||||
*/
|
||||
const ClientTls = function(options) {
|
||||
if(typeof(options) === 'string') {
|
||||
options = {path: options};
|
||||
}
|
||||
|
||||
if(!(this instanceof ClientTls)) {
|
||||
return new ClientTls(options);
|
||||
}
|
||||
Client.call(this, options);
|
||||
|
||||
const defaults = utils.merge(this.options, {
|
||||
encoding: 'utf8'
|
||||
});
|
||||
|
||||
this.options = utils.merge(defaults, options || {});
|
||||
};
|
||||
require('util').inherits(ClientTls, Client);
|
||||
|
||||
module.exports = ClientTls;
|
||||
|
||||
ClientTls.prototype._request = function(request, callback) {
|
||||
const self = this;
|
||||
|
||||
// copies options so object can be modified in this context
|
||||
const options = utils.merge({}, this.options);
|
||||
|
||||
utils.JSON.stringify(request, options, function(err, body) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
let handled = false;
|
||||
|
||||
const conn = tls.connect(options, function() {
|
||||
|
||||
conn.setEncoding(options.encoding);
|
||||
|
||||
// wont get anything for notifications, just end here
|
||||
if(utils.Request.isNotification(request)) {
|
||||
|
||||
handled = true;
|
||||
conn.end(body + '\n');
|
||||
callback();
|
||||
|
||||
} else {
|
||||
|
||||
utils.parseStream(conn, options, function(err, response) {
|
||||
handled = true;
|
||||
conn.end();
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
callback(null, response);
|
||||
});
|
||||
|
||||
conn.write(body + '\n');
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
self.emit('tcp socket', conn);
|
||||
|
||||
conn.on('error', function(err) {
|
||||
self.emit('tcp error', err);
|
||||
callback(err);
|
||||
});
|
||||
|
||||
conn.on('end', function() {
|
||||
if(!handled) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
135
node_modules/jayson/lib/client/websocket.js
generated
vendored
Normal file
135
node_modules/jayson/lib/client/websocket.js
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
'use strict';
|
||||
|
||||
const WebSocket = require('isomorphic-ws');
|
||||
const utils = require('../utils');
|
||||
const delay = require('delay');
|
||||
const Client = require('../client');
|
||||
|
||||
/**
|
||||
* Constructor for a Jayson Websocket Client
|
||||
* @class ClientWebsocket
|
||||
* @constructor
|
||||
* @extends Client
|
||||
* @param {Object} [options]
|
||||
* @param {String} [options.url] When options.ws not provided this will be the URL to open the websocket to
|
||||
* @param {ws.WebSocket} [options.ws] When not provided will create a WebSocket instance with options.url
|
||||
* @param {Number} [options.timeout] Will wait this long in ms until callbacking with an error
|
||||
* @return {ClientWebsocket}
|
||||
*/
|
||||
const ClientWebsocket = function(options) {
|
||||
if(!(this instanceof ClientWebsocket)) {
|
||||
return new ClientWebsocket(options);
|
||||
}
|
||||
Client.call(this, options);
|
||||
|
||||
const defaults = utils.merge(this.options, {});
|
||||
this.options = utils.merge(defaults, options || {});
|
||||
|
||||
const self = this;
|
||||
|
||||
this.ws = this.options.ws || new WebSocket(this.options.url);
|
||||
this.outstandingRequests = [];
|
||||
this.handlers = {};
|
||||
|
||||
this.handlers.message = function (str) {
|
||||
utils.JSON.parse(str, self.options, function(err, response) {
|
||||
if (err) {
|
||||
// invalid JSON is ignored
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(response)) {
|
||||
|
||||
// we have a batch reply
|
||||
const matchingRequest = self.outstandingRequests.find(function ([request]) {
|
||||
if (Array.isArray(request)) {
|
||||
// a batch is considered matching if at least one response id matches one request id
|
||||
return response.some(function (resp) {
|
||||
if (utils.Response.isValidResponse(resp)) {
|
||||
return request.some(function (req) {
|
||||
return req.id === resp.id;
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (matchingRequest) {
|
||||
const [ , resolve ] = matchingRequest;
|
||||
return resolve(response);
|
||||
}
|
||||
|
||||
} else if (utils.Response.isValidResponse(response)) {
|
||||
|
||||
const matchingRequest = self.outstandingRequests.find(function ([request]) {
|
||||
return !Array.isArray(request) && request.id === response.id;
|
||||
});
|
||||
|
||||
if (matchingRequest) {
|
||||
const [ , resolve ] = matchingRequest;
|
||||
return resolve(response);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
this.ws.on('message', this.handlers.message);
|
||||
};
|
||||
require('util').inherits(ClientWebsocket, Client);
|
||||
|
||||
module.exports = ClientWebsocket;
|
||||
|
||||
/**
|
||||
* @desc Removes all event listeners from Websocket instance which cancels all outstanding requests too
|
||||
*/
|
||||
ClientWebsocket.prototype.unlisten = function () {
|
||||
for (const eventName in this.handlers) {
|
||||
this.ws.off(eventName, this.handlers[eventName]);
|
||||
}
|
||||
};
|
||||
|
||||
ClientWebsocket.prototype._request = function(request, callback) {
|
||||
const self = this;
|
||||
const { ws, options } = this;
|
||||
|
||||
// we have to remove the object representing this request when the promise resolves/rejects
|
||||
let outstandingItem;
|
||||
|
||||
Promise.race([
|
||||
options.timeout > 0 ? delay(options.timeout).then(function () {
|
||||
throw new Error('timeout reached after ' + options.timeout + ' ms');
|
||||
}) : null,
|
||||
new Promise(function (resolve, reject) {
|
||||
utils.JSON.stringify(request, options, function(err, body) {
|
||||
if (err) {
|
||||
return resolve(err);
|
||||
}
|
||||
|
||||
ws.send(body);
|
||||
|
||||
if (utils.Request.isNotification(request)) {
|
||||
// notifications callback immediately since they don't have a reply
|
||||
return resolve();
|
||||
}
|
||||
|
||||
outstandingItem = [request, resolve, reject];
|
||||
self.outstandingRequests.push(outstandingItem);
|
||||
});
|
||||
}),
|
||||
].filter(v => v !== null)).then(function (result) {
|
||||
removeOutstandingRequest();
|
||||
callback(null, result);
|
||||
}).catch(function (err) {
|
||||
removeOutstandingRequest();
|
||||
callback(err);
|
||||
});
|
||||
|
||||
function removeOutstandingRequest () {
|
||||
if (!outstandingItem) {
|
||||
return;
|
||||
}
|
||||
self.outstandingRequests = self.outstandingRequests.filter(v => v !== outstandingItem);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user