import { Transport, TransportType } from './Transport' import { CallRequestDTO } from '../CallRequestDTO' import { CallResponseDTO } from '../CallResponseDTO' import { RPCClientIdentity } from '../RPCClientIdentity' import { GetDebugLogger } from '../utils/debug-logger' import { RPCClientOptions, CallOptions } from '../RPCClient' import { CallRequestTransportError } from './errors' import { getRequestShorthand } from '../utils/request' const debug = GetDebugLogger('rpc:HTTPTransport') interface HTTPTransportOptions { host: string rpcOptions: RPCClientOptions } export class HTTPTransport implements Transport { private readonly host: string private identity?: RPCClientIdentity // private inFlightCallCount: number = 0; readonly name = 'HttpTransport' readonly type = TransportType.http constructor(readonly options: HTTPTransportOptions) { this.host = options.host } /** * Checks if the transport is likely connected to the network. * * Note: This check is unreliable. `navigator.onLine` only indicates whether * the device has a network connection, not whether it can reach the server. * Callers should always handle network errors at the call site regardless * of what this method returns. */ public isConnected = (): boolean => { if (typeof window !== 'undefined') { return !!window?.navigator?.onLine } // could be node.js env, fetch should be defined return typeof fetch === 'function' } public sendRequest = async ( call: CallRequestDTO, opts: CallOptions, ): Promise => { debug('sendRequest', call) try { const body = JSON.stringify({ identity: this.identity, ...call, }) const res = await fetch(this.host, { body, cache: 'default', credentials: 'omit', headers: { 'Content-Type': 'application/json', }, method: 'POST', mode: 'cors', redirect: 'follow', referrerPolicy: 'origin', }) const string = await res.text() if (!string) throw new Error('No response received from remote') const response = JSON.parse(string) return new CallResponseDTO(response) } catch (err: any) { debug('sendRequest() error', err) throw new CallRequestTransportError( `HTTPTransport request error ${getRequestShorthand(call)} (${err?.message})`, ) } } public setIdentity = (identity?: RPCClientIdentity) => { debug('setIdentity', identity) this.identity = identity } public destroy = () => { debug('destroy') this.identity = undefined } }