From 0c52324915ebf70ca6d5bd021238235a98445fd9 Mon Sep 17 00:00:00 2001 From: Dave Horton Date: Sat, 7 Jan 2023 15:00:18 -0500 Subject: [PATCH] Bugfix/http redirect to ws (#211) * allow redirect to ws(s) url after starting with http(s) #210 * further fixes for #210 --- lib/session/call-session.js | 14 ++++++++++---- lib/tasks/task.js | 6 ++++-- lib/utils/http-requestor.js | 13 +++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/session/call-session.js b/lib/session/call-session.js index 194ce1c4..645fedcb 100644 --- a/lib/session/call-session.js +++ b/lib/session/call-session.js @@ -82,12 +82,18 @@ class CallSession extends Emitter { this._pool = srf.locals.dbHelpers.pool; + const handover = (newRequestor) => { + this.logger.info(`handover to new base url ${newRequestor.url}`); + this.requestor.removeAllListeners(); + this.application.requestor = newRequestor; + this.requestor.on('command', this._onCommand.bind(this)); + this.requestor.on('connection-dropped', this._onWsConnectionDropped.bind(this)); + this.requestor.on('handover', handover.bind(this)); + }; + this.requestor.on('command', this._onCommand.bind(this)); this.requestor.on('connection-dropped', this._onWsConnectionDropped.bind(this)); - this.requestor.on('handover', (newRequestor) => { - this.logger.info(`handover to new base url ${newRequestor.url}`); - this.application.requestor = newRequestor; - }); + this.requestor.on('handover', handover.bind(this)); } /** diff --git a/lib/tasks/task.js b/lib/tasks/task.js index ce3291d1..c6a2b80e 100644 --- a/lib/tasks/task.js +++ b/lib/tasks/task.js @@ -5,6 +5,7 @@ const assert = require('assert'); const {TaskPreconditions} = require('../utils/constants'); const normalizeJambones = require('../utils/normalize-jambones'); const WsRequestor = require('../utils/ws-requestor'); +const {TaskName} = require('../utils/constants'); const {trace} = require('@opentelemetry/api'); const specs = new Map(); const _specData = require('./specs'); @@ -157,13 +158,14 @@ class Task extends Emitter { async performAction(results, expectResponse = true) { if (this.actionHook) { + const type = this.name === TaskName.Redirect ? 'session:redirect' : 'verb:hook'; const params = results ? Object.assign(this.cs.callInfo.toJSON(), results) : this.cs.callInfo.toJSON(); - const span = this.startSpan('verb:hook', {'hook.url': this.actionHook}); + const span = this.startSpan(type, {'hook.url': this.actionHook}); const b3 = this.getTracingPropagation('b3', span); const httpHeaders = b3 && {b3}; span.setAttributes({'http.body': JSON.stringify(params)}); try { - const json = await this.cs.requestor.request('verb:hook', this.actionHook, params, httpHeaders); + const json = await this.cs.requestor.request(type, this.actionHook, params, httpHeaders); span.setAttributes({'http.statusCode': 200}); span.end(); if (expectResponse && json && Array.isArray(json)) { diff --git a/lib/utils/http-requestor.js b/lib/utils/http-requestor.js index 888f2bb6..6e71e0ff 100644 --- a/lib/utils/http-requestor.js +++ b/lib/utils/http-requestor.js @@ -2,6 +2,7 @@ const {Client, Pool} = require('undici'); const parseUrl = require('parse-url'); const assert = require('assert'); const BaseRequestor = require('./base-requestor'); +const WsRequestor = require('./ws-requestor'); const {HookMsgTypes} = require('./constants.json'); const snakeCaseKeys = require('./snakecase-keys'); const pools = new Map(); @@ -91,6 +92,18 @@ class HttpRequestor extends BaseRequestor { assert.ok, (['GET', 'POST'].includes(method), `HttpRequestor:request method must be 'GET' or 'POST' not ${method}`); const startAt = process.hrtime(); + /* if we have an absolute url, and it is ws then do a websocket connection */ + if (this._isAbsoluteUrl(url) && url.startsWith('ws')) { + this.logger.debug({hook}, 'HttpRequestor: switching to websocket connection'); + const h = typeof hook === 'object' ? hook : {url: hook}; + const requestor = new WsRequestor(this.logger, this.account_sid, h, this.secret); + if (type === 'session:redirect') { + this.close(); + this.emit('handover', requestor); + } + return requestor.request('session:new', hook, params, httpHeaders); + } + let newClient; try { let client, path, query;