11cb0ef41Sopenharmony_ci'use strict' 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst { InvalidArgumentError, RequestAbortedError, SocketError } = require('../core/errors') 41cb0ef41Sopenharmony_ciconst { AsyncResource } = require('async_hooks') 51cb0ef41Sopenharmony_ciconst util = require('../core/util') 61cb0ef41Sopenharmony_ciconst { addSignal, removeSignal } = require('./abort-signal') 71cb0ef41Sopenharmony_ciconst assert = require('assert') 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciclass UpgradeHandler extends AsyncResource { 101cb0ef41Sopenharmony_ci constructor (opts, callback) { 111cb0ef41Sopenharmony_ci if (!opts || typeof opts !== 'object') { 121cb0ef41Sopenharmony_ci throw new InvalidArgumentError('invalid opts') 131cb0ef41Sopenharmony_ci } 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ci if (typeof callback !== 'function') { 161cb0ef41Sopenharmony_ci throw new InvalidArgumentError('invalid callback') 171cb0ef41Sopenharmony_ci } 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci const { signal, opaque, responseHeaders } = opts 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { 221cb0ef41Sopenharmony_ci throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') 231cb0ef41Sopenharmony_ci } 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci super('UNDICI_UPGRADE') 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci this.responseHeaders = responseHeaders || null 281cb0ef41Sopenharmony_ci this.opaque = opaque || null 291cb0ef41Sopenharmony_ci this.callback = callback 301cb0ef41Sopenharmony_ci this.abort = null 311cb0ef41Sopenharmony_ci this.context = null 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci addSignal(this, signal) 341cb0ef41Sopenharmony_ci } 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci onConnect (abort, context) { 371cb0ef41Sopenharmony_ci if (!this.callback) { 381cb0ef41Sopenharmony_ci throw new RequestAbortedError() 391cb0ef41Sopenharmony_ci } 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci this.abort = abort 421cb0ef41Sopenharmony_ci this.context = null 431cb0ef41Sopenharmony_ci } 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci onHeaders () { 461cb0ef41Sopenharmony_ci throw new SocketError('bad upgrade', null) 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci onUpgrade (statusCode, rawHeaders, socket) { 501cb0ef41Sopenharmony_ci const { callback, opaque, context } = this 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci assert.strictEqual(statusCode, 101) 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci removeSignal(this) 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci this.callback = null 571cb0ef41Sopenharmony_ci const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) 581cb0ef41Sopenharmony_ci this.runInAsyncScope(callback, null, null, { 591cb0ef41Sopenharmony_ci headers, 601cb0ef41Sopenharmony_ci socket, 611cb0ef41Sopenharmony_ci opaque, 621cb0ef41Sopenharmony_ci context 631cb0ef41Sopenharmony_ci }) 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci onError (err) { 671cb0ef41Sopenharmony_ci const { callback, opaque } = this 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci removeSignal(this) 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci if (callback) { 721cb0ef41Sopenharmony_ci this.callback = null 731cb0ef41Sopenharmony_ci queueMicrotask(() => { 741cb0ef41Sopenharmony_ci this.runInAsyncScope(callback, null, err, { opaque }) 751cb0ef41Sopenharmony_ci }) 761cb0ef41Sopenharmony_ci } 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci} 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_cifunction upgrade (opts, callback) { 811cb0ef41Sopenharmony_ci if (callback === undefined) { 821cb0ef41Sopenharmony_ci return new Promise((resolve, reject) => { 831cb0ef41Sopenharmony_ci upgrade.call(this, opts, (err, data) => { 841cb0ef41Sopenharmony_ci return err ? reject(err) : resolve(data) 851cb0ef41Sopenharmony_ci }) 861cb0ef41Sopenharmony_ci }) 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci try { 901cb0ef41Sopenharmony_ci const upgradeHandler = new UpgradeHandler(opts, callback) 911cb0ef41Sopenharmony_ci this.dispatch({ 921cb0ef41Sopenharmony_ci ...opts, 931cb0ef41Sopenharmony_ci method: opts.method || 'GET', 941cb0ef41Sopenharmony_ci upgrade: opts.protocol || 'Websocket' 951cb0ef41Sopenharmony_ci }, upgradeHandler) 961cb0ef41Sopenharmony_ci } catch (err) { 971cb0ef41Sopenharmony_ci if (typeof callback !== 'function') { 981cb0ef41Sopenharmony_ci throw err 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci const opaque = opts && opts.opaque 1011cb0ef41Sopenharmony_ci queueMicrotask(() => callback(err, { opaque })) 1021cb0ef41Sopenharmony_ci } 1031cb0ef41Sopenharmony_ci} 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_cimodule.exports = upgrade 106