{.push raises: [Defect].} import pkg/websock/websock, ./servers/[httpserver], ./clients/[httpclient, websocketclient] type ClientKind* = enum Http, WebSocket ClientConfig* = object case kind*: ClientKind of Http: httpUri*: string of WebSocket: wsUri*: string compression*: bool flags*: set[TLSFlags] RpcProxy* = ref object of RootRef rpcHttpServer*: RpcHttpServer case kind*: ClientKind of Http: httpUri*: string httpClient*: RpcHttpClient of WebSocket: wsUri*: string webSocketClient*: RpcWebSocketClient compression*: bool flags*: set[TLSFlags] # TODO Add validations that provided uri-s are correct https/wss uri and retrun # Result[string, ClientConfig] proc getHttpClientConfig*(uri: string): ClientConfig = ClientConfig(kind: Http, httpUri: uri) proc getWebSocketClientConfig*( uri: string, compression: bool = false, flags: set[TLSFlags] = { NoVerifyHost, NoVerifyServerName}): ClientConfig = ClientConfig(kind: WebSocket, wsUri: uri, compression: compression, flags: flags) proc proxyCall(client: RpcClient, name: string): RpcProc = return proc (params: JsonNode): Future[StringOfJson] {.async.} = let res = await client.call(name, params) return StringOfJson($res) proc getClient(proxy: RpcProxy): RpcClient = case proxy.kind of Http: proxy.httpClient of WebSocket: proxy.webSocketClient proc new*(T: type RpcProxy, server: RpcHttpServer, cfg: ClientConfig): T = case cfg.kind of Http: let client = newRpcHttpClient() return T(rpcHttpServer: server, kind: Http, httpUri: cfg.httpUri, httpClient: client) of WebSocket: let client = newRpcWebSocketClient() return T( rpcHttpServer: server, kind: WebSocket, wsUri: cfg.wsUri, webSocketClient: client, compression: cfg.compression, flags: cfg.flags ) proc new*(T: type RpcProxy, listenAddresses: openArray[TransportAddress], cfg: ClientConfig): T {.raises: [Defect, CatchableError].} = RpcProxy.new(newRpcHttpServer(listenAddresses, RpcRouter.init()), cfg) proc new*(T: type RpcProxy, listenAddresses: openArray[string], cfg: ClientConfig): T {.raises: [Defect, CatchableError].} = RpcProxy.new(newRpcHttpServer(listenAddresses, RpcRouter.init()), cfg) proc connectToProxy(proxy: RpcProxy): Future[void] = case proxy.kind of Http: return proxy.httpClient.connect(proxy.httpUri) of WebSocket: return proxy.webSocketClient.connect(proxy.wsUri, proxy.compression, proxy.flags) proc start*(proxy: RpcProxy) {.async.} = proxy.rpcHttpServer.start() await proxy.connectToProxy() template rpc*(server: RpcProxy, path: string, body: untyped): untyped = server.rpcHttpServer.rpc(path, body) proc registerProxyMethod*(proxy: var RpcProxy, methodName: string) = try: proxy.rpcHttpServer.register(methodName, proxyCall(proxy.getClient(), methodName)) except CatchableError as err: # Adding proc type to table gives invalid exception tracking, see Nim bug: https://github.com/nim-lang/Nim/issues/18376 raiseAssert err.msg proc stop*(proxy: RpcProxy) {.async.} = await proxy.getClient().close() proxy.rpcHttpServer.stop() proc closeWait*(proxy: RpcProxy) {.async.} = await proxy.rpcHttpServer.closeWait()