Skip to content

Commit 5f5e48e

Browse files
author
Chris Clark
committedDec 1, 2015
Add support for client certificates
1 parent cfc21fd commit 5f5e48e

File tree

3 files changed

+44
-19
lines changed

3 files changed

+44
-19
lines changed
 

‎docs/index.md

+3
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ The RippleAPI constructor optionally takes one argument, an object with the foll
112112
Name | Type | Description
113113
---- | ---- | -----------
114114
authorization | string | *Optional* Username and password for HTTP basic authentication to the rippled server in the format **username:password**.
115+
certificate | string | *Optional* A string containing the certificate key of the client in PEM format. (Can be an array of certificates).
115116
feeCushion | number | *Optional* Factor to multiply estimated fee by to provide a cushion in case the required fee rises during submission of a transaction. Defaults to `1.2`.
117+
key | string | *Optional* A string containing the private key of the client in PEM format. (Can be an array of keys).
118+
passphrase | string | *Optional* The passphrase for the private key of the client.
116119
proxy | uri string | *Optional* URI for HTTP/HTTPS proxy to use to connect to the rippled server.
117120
proxyAuthorization | string | *Optional* Username and password for HTTP basic authentication to the proxy in the format **username:password**.
118121
server | uri string | *Optional* URI for rippled websocket port to connect to. Must start with `wss://` or `ws://`.

‎src/common/connection.js

+29-19
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
'use strict';
2+
const _ = require('lodash');
23
const {EventEmitter} = require('events');
34
const WebSocket = require('ws');
45
const parseURL = require('url').parse;
@@ -26,6 +27,9 @@ class Connection extends EventEmitter {
2627
this._proxyAuthorization = options.proxyAuthorization;
2728
this._authorization = options.authorization;
2829
this._trustedCertificates = options.trustedCertificates;
30+
this._key = options.key;
31+
this._passphrase = options.passphrase;
32+
this._certificate = options.certificate;
2933
this._timeout = options.timeout || (20 * 1000);
3034
this._isReady = false;
3135
this._ws = null;
@@ -104,20 +108,21 @@ class Connection extends EventEmitter {
104108
});
105109
}
106110

107-
_createWebSocket(url, proxyURL, proxyAuthorization, authorization,
108-
trustedCertificates) {
111+
_createWebSocket() {
109112
const options = {};
110-
if (proxyURL !== undefined) {
111-
const parsedURL = parseURL(url);
112-
const proxyOptions = parseURL(proxyURL);
113-
proxyOptions.secureEndpoint = (parsedURL.protocol === 'wss:');
114-
proxyOptions.secureProxy = (proxyOptions.protocol === 'https:');
115-
if (proxyAuthorization !== undefined) {
116-
proxyOptions.auth = proxyAuthorization;
117-
}
118-
if (trustedCertificates !== undefined) {
119-
proxyOptions.ca = trustedCertificates;
120-
}
113+
if (this._proxyURL !== undefined) {
114+
const parsedURL = parseURL(this._url);
115+
const parsedProxyURL = parseURL(this._proxyURL);
116+
const proxyOverrides = _.omit({
117+
secureEndpoint: (parsedURL.protocol === 'wss:'),
118+
secureProxy: (parsedProxyURL.protocol === 'https:'),
119+
auth: this._proxyAuthorization,
120+
ca: this._trustedCertificates,
121+
key: this._key,
122+
passphrase: this._passphrase,
123+
cert: this._certificate
124+
}, _.isUndefined);
125+
const proxyOptions = _.assign({}, parsedProxyURL, proxyOverrides);
121126
let HttpsProxyAgent;
122127
try {
123128
HttpsProxyAgent = require('https-proxy-agent');
@@ -126,11 +131,18 @@ class Connection extends EventEmitter {
126131
}
127132
options.agent = new HttpsProxyAgent(proxyOptions);
128133
}
129-
if (authorization !== undefined) {
130-
const base64 = new Buffer(authorization).toString('base64');
134+
if (this._authorization !== undefined) {
135+
const base64 = new Buffer(this._authorization).toString('base64');
131136
options.headers = {Authorization: `Basic ${base64}`};
132137
}
133-
const websocket = new WebSocket(url, options);
138+
const optionsOverrides = _.omit({
139+
ca: this._trustedCertificates,
140+
key: this._key,
141+
passphrase: this._passphrase,
142+
cert: this._certificate
143+
}, _.isUndefined);
144+
const websocketOptions = _.assign({}, options, optionsOverrides);
145+
const websocket = new WebSocket(this._url, websocketOptions);
134146
// we will have a listener for each outstanding request,
135147
// so we have to raise the limit (the default is 10)
136148
websocket.setMaxListeners(Infinity);
@@ -148,9 +160,7 @@ class Connection extends EventEmitter {
148160
} else if (this._state === WebSocket.CONNECTING) {
149161
this._ws.once('open', resolve);
150162
} else {
151-
this._ws = this._createWebSocket(this._url, this._proxyURL,
152-
this._proxyAuthorization, this._authorization,
153-
this._trustedCertificates);
163+
this._ws = this._createWebSocket();
154164
this._ws.on('message', this._onMessage.bind(this));
155165
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this);
156166
this._ws.once('close', this._onUnexpectedCloseBound);

‎src/common/schemas/input/api-options.json

+12
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@
4242
"type": "string",
4343
"description": "A PEM-formatted SSL certificate to trust when connecting to a proxy."
4444
}
45+
},
46+
"key": {
47+
"type": "string",
48+
"description": "A string containing the private key of the client in PEM format. (Can be an array of keys)."
49+
},
50+
"passphrase": {
51+
"type": "string",
52+
"description": "The passphrase for the private key of the client."
53+
},
54+
"certificate": {
55+
"type": "string",
56+
"description": "A string containing the certificate key of the client in PEM format. (Can be an array of certificates)."
4557
}
4658
},
4759
"additionalProperties": false

0 commit comments

Comments
 (0)
Please sign in to comment.