Skip to content

Commit

Permalink
WebSocket intercept enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
rentallect committed Feb 5, 2024
1 parent 7895589 commit 56f4a4f
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 70 deletions.
3 changes: 2 additions & 1 deletion src/channel/channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,7 @@ class ZitiChannel {

// this._zitiContext.logger.debug(`send (no wait) -> ch[${this._id}] conn[${(options.conn ? options.conn.id : 'n/a')}] seq[${messageId}] contentType[${contentType}] bodyLen[${(body ? body.length : 'n/a')}] body[${(body ? body.toString() : 'n/a')}]`);
this._zitiContext.logger.debug(`ch.sendMessageNoWait() -> ch[${this._id}] conn[${(options.conn ? options.conn.id : 'n/a')}] socket[${options.conn ? options.conn.socket._id : 'n/a'}][${options.conn ? options.conn.socket.isNew : 'n/a'}] seq[${messageId}] contentType[${contentType}] byteLength[${(body ? body.byteLength : 'n/a')}]`);
this._zitiContext.logger.debug(`ch.sendMessageNoWait() -> body[${(body ? body.toString() : 'n/a')}]`);

this._sendMarshaled(contentType, headers, body, options, messageId);
}
Expand Down Expand Up @@ -1111,7 +1112,7 @@ class ZitiChannel {
if (len > 2000) {
len = 2000;
}
// this._zitiContext.logger.trace("recv <- unencrypted_data (first 2000): %s", m1.substring(0, len));
this._zitiContext.logger.trace("recv <- unencrypted_data (first 2000): %s", m1.substring(0, len));

//
// let dbgStr = m1.substring(0, len);
Expand Down
44 changes: 36 additions & 8 deletions src/context/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,24 @@ class ZitiContext extends EventEmitter {

}

/**
* Remain in lazy-sleepy loop until context is initialized.
*
* @param {*} ctx
*/
awaitInitializationComplete() {
let self = this;
return new Promise((resolve) => {
(function waitForInitializationComplete() {
if (!self._initialized) {
setTimeout(waitForInitializationComplete, 10);
} else {
return resolve();
}
})();
});
}


/**
*
Expand Down Expand Up @@ -1213,6 +1231,8 @@ class ZitiContext extends EventEmitter {

let dst_port;

scheme = scheme.replace(':', '');

find(portRanges, function(portRange) {
if (isEqual( scheme, 'https' )) {
if (isEqual( portRange.low, 443 ) || isEqual( portRange.high, 443 )) {
Expand Down Expand Up @@ -1722,12 +1742,16 @@ class ZitiContext extends EventEmitter {
throw new Error( error );
});

if (isUndefined(serviceName)) {

serviceName = await self.getServiceNameByHostName(hostname).catch(( error ) => {
throw new Error( error );
});
if (parsedURL.port === '') {

if (isUndefined(serviceName)) {

serviceName = await self.getServiceNameByHostName(hostname).catch(( error ) => {
throw new Error( error );
});

}

}

if (isUndefined(serviceName)) {
Expand All @@ -1746,7 +1770,7 @@ class ZitiContext extends EventEmitter {

}

async shouldRouteOverZitiSync(url) {
shouldRouteOverZitiSync(url) {

let parsedURL = new URL(url);
let hostname = parsedURL.hostname;
Expand All @@ -1767,7 +1791,9 @@ class ZitiContext extends EventEmitter {
return true;
}

return self._getMatchConfigInterceptV1( obj.config['intercept.v1'], hostname, port );
if (self._getMatchConfigInterceptV1( obj.config['intercept.v1'], hostname, port )) {
return true;
}

}), 'name');

Expand Down Expand Up @@ -1878,7 +1904,9 @@ class ZitiContext extends EventEmitter {
return true;
}

return self._getMatchConfigInterceptV1( obj.config['intercept.v1'], hostname, port );
if (self._getMatchConfigInterceptV1( obj.config['intercept.v1'], hostname, port )) {
return true;
}

}), 'name');

Expand Down
73 changes: 12 additions & 61 deletions src/http/ziti-websocket-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ class ZitiWebSocketWrapper extends EventEmitter {
get OPEN() {
return ZitiWebSocketWrapper.OPEN;
}

get READYSTATE() {
return this.readyState;
}

/**
* This deviates from the WHATWG interface since ws doesn't support the
* required default "blob" type (instead we define a custom "nodebuffer"
Expand Down Expand Up @@ -469,6 +472,8 @@ export {
*/
async function initAsClient(websocket, address, protocols, options) {

await websocket._zitiContext.awaitInitializationComplete();

let serviceName;

const opts = {
Expand Down Expand Up @@ -532,65 +537,12 @@ async function initAsClient(websocket, address, protocols, options) {
const get = http.get;
let perMessageDeflate;

// await loadCookies(parsedUrl.hostname);

// We only want to intercept fetch requests that target the Ziti BrowZer Bootstrapper
var regex = new RegExp( websocket._zitiConfig.browzer.bootstrapper.self.host, 'g' );

if (address.match( regex )) { // the request is targeting the Ziti BrowZer Bootstrapper

var newUrl = new URL( address );
newUrl.hostname = websocket._zitiConfig.browzer.bootstrapper.target.service;
newUrl.port = websocket._zitiConfig.browzer.bootstrapper.target.port;
websocket._zitiContext.logger.debug( 'ZitiWebSocketWrapper: transformed URL: ', newUrl.toString());

serviceName = await websocket._zitiContext.shouldRouteOverZiti( newUrl );

if (isUndefined(serviceName)) { // If we have no serviceConfig associated with the hostname:port, do not intercept
websocket._zitiContext.logger.warn(`ZitiWebSocketWrapper(): no associated serviceConfig, bypassing intercept of [${address}]`);
opts.createConnection = isSecure ? tlsConnect : netConnect;
opts.host = parsedUrl.hostname.startsWith('[')
? parsedUrl.hostname.slice(1, -1)
: parsedUrl.hostname;
} else {

opts.createConnection = zitiConnect; // We're going over Ziti

let configHostAndPort = await websocket._zitiContext.getConfigHostAndPortByServiceName (serviceName);

newUrl.protocol = websocket._zitiConfig.browzer.bootstrapper.target.scheme + ":";
opts.href = newUrl.protocol + '//' + configHostAndPort.host.toLowerCase() + newUrl.pathname + newUrl.search;
opts.origin = websocket._zitiConfig.browzer.bootstrapper.target.scheme + "://" + configHostAndPort.host.toLowerCase() + ":" + configHostAndPort.port;
opts.host = serviceName;
}

} else {
serviceName = await websocket._zitiContext.shouldRouteOverZiti( address );

if (!isUndefined(serviceName)) {

let newUrl = new URL( address );

opts.createConnection = zitiConnect; // We're going over Ziti

let configHostAndPort = await websocket._zitiContext.getConfigHostAndPortByServiceName (serviceName);

newUrl.protocol = websocket._zitiConfig.browzer.bootstrapper.target.scheme + ":";
opts.href = newUrl.protocol + '//' + configHostAndPort.host.toLowerCase() + newUrl.pathname + newUrl.search;
opts.origin = websocket._zitiConfig.browzer.bootstrapper.target.scheme + "://" + configHostAndPort.host.toLowerCase() + ":" + configHostAndPort.port;
opts.host = serviceName;

}
else { // the request is targeting the raw internet

websocket._zitiContext.logger.warn(`ZitiWebSocketWrapper(): no associated serviceConfig, bypassing intercept of [${address}]`);
opts.createConnection = isSecure ? tlsConnect : netConnect;
opts.host = parsedUrl.hostname.startsWith('[')
? parsedUrl.hostname.slice(1, -1)
: parsedUrl.hostname;
}
}
opts.createConnection = zitiConnect; // We're going over Ziti

newUrl.protocol = websocket._zitiConfig.browzer.bootstrapper.target.scheme + ":";
opts.href = newUrl.protocol + '//' + opts.configHostAndPort.host.toLowerCase() + newUrl.pathname + newUrl.search;
opts.origin = websocket._zitiConfig.browzer.bootstrapper.target.scheme + "://" + opts.configHostAndPort.host.toLowerCase() + ":" + opts.configHostAndPort.port;
opts.host = opts.serviceName;

opts.defaultPort = opts.defaultPort || defaultPort;
opts.port = parsedUrl.port || defaultPort;
Expand Down Expand Up @@ -655,12 +607,11 @@ async function initAsClient(websocket, address, protocols, options) {
opts.path = parts[1];
}

opts.serviceName = serviceName;
opts.serviceScheme = websocket._zitiConfig.browzer.bootstrapper.target.scheme;
opts.serviceConnectAppData = await websocket._zitiContext.getConnectAppDataByServiceName(opts.serviceName, opts.serviceScheme);

// build HTTP request object
let request = new ZitiHttpRequest(serviceName, opts.href, opts, websocket._zitiContext);
let request = new ZitiHttpRequest(opts.serviceName, opts.href, opts, websocket._zitiContext);
const req_options = await request.getRequestOptions();
req_options.isWebSocket = true;

Expand Down

0 comments on commit 56f4a4f

Please sign in to comment.