diff --git a/examples/autobahn_client.nim b/examples/autobahn_client.nim index ab5c98ca..4f015672 100644 --- a/examples/autobahn_client.nim +++ b/examples/autobahn_client.nim @@ -19,19 +19,18 @@ const # so we are using different port when defined tls: const - agent = "websock secure client" + agent = "websock-secure-client" secure = true serverPort = 9002 else: const - agent = "websock client" + agent = "websock-client" secure = false serverPort = 9001 proc connectServer(path: string, factories: seq[ExtFactory] = @[]): Future[WSSession] {.async.} = let ws = await WebSocket.connect( - host = "127.0.0.1", - port = Port(serverPort), + host = "127.0.0.1:$1" % [$serverPort], path = path, secure=secure, flags=clientFlags, diff --git a/examples/client.nim b/examples/client.nim index 90f4f27f..133e416e 100644 --- a/examples/client.nim +++ b/examples/client.nim @@ -17,14 +17,12 @@ import ../websock/websock proc main() {.async.} = let ws = when defined tls: await WebSocket.connect( - "127.0.0.1", - Port(8888), + "127.0.0.1:8888", path = "/wss", flags = {TLSFlags.NoVerifyHost, TLSFlags.NoVerifyServerName}) else: await WebSocket.connect( - "127.0.0.1", - Port(8888), + "127.0.0.1:8888", path = "/ws") trace "Websocket client: ", State = ws.readyState diff --git a/tests/extensions/testcompression.nim b/tests/extensions/testcompression.nim index 0fb1842a..72eeeea3 100644 --- a/tests/extensions/testcompression.nim +++ b/tests/extensions/testcompression.nim @@ -48,8 +48,7 @@ suite "permessage deflate compression": server.start() let client = await WebSocket.connect( - host = "127.0.0.1", - port = Port(8888), + host = "127.0.0.1:8888", path = "/ws", protocols = @["proto"], factories = @[deflateFactory] @@ -89,8 +88,7 @@ suite "permessage deflate compression": server.start() let client = await WebSocket.connect( - host = "127.0.0.1", - port = Port(8888), + host = "127.0.0.1:8888", path = "/ws", protocols = @["proto"], factories = @[deflateFactory] diff --git a/tests/extensions/testexts.nim b/tests/extensions/testexts.nim index bddb1a5f..8269cd53 100644 --- a/tests/extensions/testexts.nim +++ b/tests/extensions/testexts.nim @@ -43,8 +43,7 @@ suite "multiple extensions flow": server.start() let client = await WebSocket.connect( - host = "127.0.0.1", - port = Port(8888), + host = "127.0.0.1:8888", path = "/ws", protocols = @["proto"], factories = @[hexFactory, base64Factory] @@ -76,8 +75,7 @@ suite "multiple extensions flow": server.start() let client = await WebSocket.connect( - host = "127.0.0.1", - port = Port(8888), + host = "127.0.0.1:8888", path = "/ws", protocols = @["proto"], factories = @[base64Factory, hexFactory] diff --git a/tests/helpers.nim b/tests/helpers.nim index 39703aae..2b65e4bd 100644 --- a/tests/helpers.nim +++ b/tests/helpers.nim @@ -96,7 +96,7 @@ proc connectClient*( rng: Rng = nil): Future[WSSession] {.async.} = let secure = when defined secure: true else: false return await WebSocket.connect( - address = address, + host = address, flags = flags, path = path, secure = secure, diff --git a/tests/testutf8.nim b/tests/testutf8.nim index 00b658b3..1b5f38ff 100644 --- a/tests/testutf8.nim +++ b/tests/testutf8.nim @@ -110,8 +110,7 @@ suite "UTF-8 validator in action": server.start() let session = await WebSocket.connect( - "127.0.0.1", - Port(8888), + "127.0.0.1:8888", path = "/ws", protocols = @["proto"], ) @@ -152,8 +151,7 @@ suite "UTF-8 validator in action": server.start() let session = await WebSocket.connect( - "127.0.0.1", - Port(8888), + "127.0.0.1:8888", path = "/ws", protocols = @["proto"], ) @@ -178,8 +176,7 @@ suite "UTF-8 validator in action": server.start() let session = await WebSocket.connect( - "127.0.0.1", - Port(8888), + "127.0.0.1:8888", path = "/ws", protocols = @["proto"] ) @@ -204,8 +201,7 @@ suite "UTF-8 validator in action": server.start() let session = await WebSocket.connect( - "127.0.0.1", - Port(8888), + "127.0.0.1:8888", path = "/ws", protocols = @["proto"] ) diff --git a/tests/testwebsockets.nim b/tests/testwebsockets.nim index 25060672..9b3a241c 100644 --- a/tests/testwebsockets.nim +++ b/tests/testwebsockets.nim @@ -33,7 +33,6 @@ suite "Test handshake": test "Should not select incorrect protocol": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath - let server = WSServer.new(protos = ["proto"]) ws = await server.handleRequest(request) diff --git a/websock/http/client.nim b/websock/http/client.nim index fdf0a4d6..0c37f060 100644 --- a/websock/http/client.nim +++ b/websock/http/client.nim @@ -103,9 +103,6 @@ proc request*( else: url - if requestUrl.scheme == "": - raise newException(HttpError, "No uri scheme supplied.") - let headerString = generateHeaders(requestUrl, httpMethod, client.version, headers) await client.stream.writer.write(headerString) @@ -129,7 +126,8 @@ proc connect*( version = HttpVersion11, tlsFlags: set[TLSFlags] = {}, tlsMinVersion = TLSVersion.TLS11, - tlsMaxVersion = TLSVersion.TLS12): Future[T] {.async.} = + tlsMaxVersion = TLSVersion.TLS12, + hostName = ""): Future[T] {.async.} = let transp = await connect(address) let client = T( @@ -150,7 +148,7 @@ proc connect*( let tlsStream = newTLSClientAsyncStream( stream.reader, stream.writer, - address.host, + serverName = hostName, minVersion = tlsMinVersion, maxVersion = tlsMaxVersion, flags = tlsFlags) @@ -167,16 +165,27 @@ proc connect*( proc connect*( T: typedesc[HttpClient | TlsHttpClient], host: string, - port: int = 80, version = HttpVersion11, tlsFlags: set[TLSFlags] = {}, tlsMinVersion = TLSVersion.TLS11, tlsMaxVersion = TLSVersion.TLS12): Future[T] - {.raises: [Defect, HttpError].} = + {.async, raises: [Defect, HttpError].} = - let address = try: - initTAddress(host, port) - except TransportAddressError as exc: - raise newException(HttpError, exc.msg) + let hostPort = host.split(":") + let addrs = resolveTAddress(host) + for a in addrs: + try: + let conn = await T.connect( + a, + version, + tlsFlags, + tlsMinVersion, + tlsMaxVersion, + hostName = hostPort[0]) - return T.connect(address, version, tlsFlags, tlsMinVersion, tlsMaxVersion) + return conn + except TransportError as exc: + trace "Error connecting to address", address = $a, exc = exc.msg + + raise newException(HttpError, + "Unable to connect to host on any address!") diff --git a/websock/types.nim b/websock/types.nim index bd24dac3..1f172efe 100644 --- a/websock/types.nim +++ b/websock/types.nim @@ -103,8 +103,8 @@ type ExtFactoryProc* = proc( isServer: bool, - args: seq[ExtParam]): Result[Ext, string] {. - gcsafe, raises: [Defect].} + args: seq[ExtParam]): Result[Ext, string] + {.gcsafe, raises: [Defect].} ExtFactory* = object name*: string diff --git a/websock/websock.nim b/websock/websock.nim index 7f7330d5..e720425e 100644 --- a/websock/websock.nim +++ b/websock/websock.nim @@ -105,9 +105,11 @@ proc selectExt(isServer: bool, proc connect*( _: type WebSocket, - uri: Uri, + host: string | TransportAddress, + path: string, protocols: seq[string] = @[], factories: seq[ExtFactory] = @[], + secure = false, flags: set[TLSFlags] = {}, version = WSDefaultVersion, frameSize = WSDefaultFrameSize, @@ -115,22 +117,15 @@ proc connect*( onPong: ControlCb = nil, onClose: CloseCb = nil, rng: Rng = nil): Future[WSSession] {.async.} = - ## create a new websockets client - ## - var rng = if isNil(rng): newRng() else: rng - var key = Base64Pad.encode(genWebSecKey(rng)) - var uri = uri - let client = case uri.scheme: - of "wss": - uri.scheme = "https" - await TlsHttpClient.connect(uri.hostname, uri.port.parseInt(), tlsFlags = flags) - of "ws": - uri.scheme = "http" - await HttpClient.connect(uri.hostname, uri.port.parseInt()) + let + rng = if isNil(rng): newRng() else: rng + key = Base64Pad.encode(genWebSecKey(rng)) + + let client = if secure: + await TlsHttpClient.connect(host, tlsFlags = flags) else: - raise newException(WSWrongUriSchemeError, - "uri scheme has to be 'ws' or 'wss'") + await HttpClient.connect(host) let headerData = [ ("Connection", "Upgrade"), @@ -138,7 +133,7 @@ proc connect*( ("Cache-Control", "no-cache"), ("Sec-WebSocket-Version", $version), ("Sec-WebSocket-Key", key), - ("Host", uri.hostname & ":" & uri.port)] + ("Host", $host)] var headers = HttpTable.init(headerData) if protocols.len > 0: @@ -154,7 +149,7 @@ proc connect*( headers.add("Sec-WebSocket-Extensions", extOffer) let response = try: - await client.request(uri, headers = headers) + await client.request(path, headers = headers) except CatchableError as exc: trace "Websocket failed during handshake", exc = exc.msg await client.close() @@ -195,63 +190,35 @@ proc connect*( proc connect*( _: type WebSocket, - address: TransportAddress, - path: string, + uri: Uri, protocols: seq[string] = @[], factories: seq[ExtFactory] = @[], - secure = false, flags: set[TLSFlags] = {}, version = WSDefaultVersion, frameSize = WSDefaultFrameSize, onPing: ControlCb = nil, onPong: ControlCb = nil, onClose: CloseCb = nil, - rng: Rng = nil): Future[WSSession] {.async.} = + rng: Rng = nil): Future[WSSession] + {.raises: [Defect, WSWrongUriSchemeError].} = ## Create a new websockets client - ## using a string path + ## using a Uri ## - var uri = if secure: - &"wss://" + let secure = case uri.scheme: + of "wss": true + of "ws": false else: - &"ws://" + raise newException(WSWrongUriSchemeError, + "uri scheme has to be 'ws' or 'wss'") - uri &= address.host & ":" & $address.port - if path.startsWith("/"): - uri.add path - else: - uri.add &"/{path}" + var uri = uri + if uri.port.len <= 0: + uri.port = if secure: "443" else: "80" - return await WebSocket.connect( - uri = parseUri(uri), - protocols = protocols, - factories = factories, - flags = flags, - version = version, - frameSize = frameSize, - onPing = onPing, - onPong = onPong, - onClose = onClose) - -proc connect*( - _: type WebSocket, - host: string, - port: Port, - path: string, - protocols: seq[string] = @[], - factories: seq[ExtFactory] = @[], - secure = false, - flags: set[TLSFlags] = {}, - version = WSDefaultVersion, - frameSize = WSDefaultFrameSize, - onPing: ControlCb = nil, - onPong: ControlCb = nil, - onClose: CloseCb = nil, - rng: Rng = nil): Future[WSSession] {.async.} = - - return await WebSocket.connect( - address = initTAddress(host, port), - path = path, + return WebSocket.connect( + host = uri.hostname & ":" & uri.port, + path = uri.path, protocols = protocols, factories = factories, secure = secure,