@@ -11,7 +11,14 @@ import {
1111 RemoteConnector
1212} from '@powersync/common' ;
1313import { BSON } from 'bson' ;
14- import { Dispatcher , EnvHttpProxyAgent , ErrorEvent , WebSocket as UndiciWebSocket } from 'undici' ;
14+ import {
15+ Dispatcher ,
16+ EnvHttpProxyAgent ,
17+ ErrorEvent ,
18+ getGlobalDispatcher ,
19+ ProxyAgent ,
20+ WebSocket as UndiciWebSocket
21+ } from 'undici' ;
1522import { ErrorRecordingDispatcher } from './ErrorRecordingDispatcher.js' ;
1623
1724export const STREAMING_POST_TIMEOUT_MS = 30_000 ;
@@ -35,51 +42,64 @@ export type NodeCustomConnectionOptions = {
3542export type NodeRemoteOptions = AbstractRemoteOptions & NodeCustomConnectionOptions ;
3643
3744export class NodeRemote extends AbstractRemote {
38- private dispatcher : Dispatcher ;
45+ private wsDispatcher : Dispatcher | undefined ;
3946
4047 constructor (
4148 protected connector : RemoteConnector ,
4249 protected logger : ILogger = DEFAULT_REMOTE_LOGGER ,
4350 options ?: Partial < NodeRemoteOptions >
4451 ) {
45- // EnvHttpProxyAgent automatically uses relevant env vars for HTTP
46- const dispatcher = options ?. dispatcher ?? new EnvHttpProxyAgent ( ) ;
52+ const fetchDispatcher = options ?. dispatcher ?? defaultFetchDispatcher ( ) ;
4753
4854 super ( connector , logger , {
4955 fetchImplementation : options ?. fetchImplementation ?? new NodeFetchProvider ( ) ,
5056 fetchOptions : {
51- dispatcher
57+ dispatcher : fetchDispatcher
5258 } ,
5359 ...( options ?? { } )
5460 } ) ;
5561
56- this . dispatcher = dispatcher ;
62+ this . wsDispatcher = options ?. dispatcher ;
5763 }
5864
5965 protected createSocket ( url : string ) : globalThis . WebSocket {
6066 // Create dedicated dispatcher for this WebSocket
61- let ws : UndiciWebSocket | undefined ;
62- const onError = ( error : Error ) => {
67+ const baseDispatcher = this . getWebsocketDispatcher ( url ) ;
68+ const errorRecordingDispatcher = new ErrorRecordingDispatcher ( baseDispatcher ) ;
69+
70+ // Create WebSocket with dedicated dispatcher
71+ const ws = new UndiciWebSocket ( url , {
72+ dispatcher : errorRecordingDispatcher ,
73+ headers : {
74+ 'User-Agent' : this . getUserAgent ( )
75+ }
76+ } ) ;
77+
78+ errorRecordingDispatcher . onError = ( error : Error ) => {
6379 // When we receive an error from the Dispatcher, emit the event on the websocket.
6480 // This will take precedence over the WebSocket's own error event, giving more details on what went wrong.
6581 const event = new ErrorEvent ( 'error' , {
6682 error,
6783 message : error . message
6884 } ) ;
69- ws ? .dispatchEvent ( event ) ;
85+ ws . dispatchEvent ( event ) ;
7086 } ;
7187
72- const errorRecordingDispatcher = new ErrorRecordingDispatcher ( this . dispatcher , onError ) ;
88+ return ws as globalThis . WebSocket ;
89+ }
7390
74- // Create WebSocket with dedicated dispatcher
75- ws = new UndiciWebSocket ( url , {
76- dispatcher : errorRecordingDispatcher ,
77- headers : {
78- 'User-Agent' : this . getUserAgent ( )
79- }
80- } ) ;
91+ protected getWebsocketDispatcher ( url : string ) {
92+ if ( this . wsDispatcher != null ) {
93+ return this . wsDispatcher ;
94+ }
8195
82- return ws as globalThis . WebSocket ;
96+ const protocol = new URL ( url ) . protocol . replace ( ':' , '' ) ;
97+ const proxy = getProxyForProtocol ( protocol ) ;
98+ if ( proxy != null ) {
99+ return new ProxyAgent ( proxy ) ;
100+ } else {
101+ return getGlobalDispatcher ( ) ;
102+ }
83103 }
84104
85105 getUserAgent ( ) : string {
@@ -95,3 +115,21 @@ export class NodeRemote extends AbstractRemote {
95115 return BSON ;
96116 }
97117}
118+
119+ function defaultFetchDispatcher ( ) : Dispatcher {
120+ // EnvHttpProxyAgent automatically uses HTTP_PROXY, HTTPS_PROXY and NO_PROXY env vars by default.
121+ // We add ALL_PROXY support.
122+ return new EnvHttpProxyAgent ( {
123+ httpProxy : getProxyForProtocol ( 'http' ) ,
124+ httpsProxy : getProxyForProtocol ( 'https' )
125+ } ) ;
126+ }
127+
128+ function getProxyForProtocol ( protocol : string ) : string | undefined {
129+ return (
130+ process . env [ `${ protocol . toLowerCase ( ) } _proxy` ] ??
131+ process . env [ `${ protocol . toUpperCase ( ) } _PROXY` ] ??
132+ process . env [ `all_proxy` ] ??
133+ process . env [ `ALL_PROXY` ]
134+ ) ;
135+ }
0 commit comments