add support for DNS resolution (#81)
* add support for DNS resolution - reworked API to be more consistent - string addresses and Uri types will be now resolved - made the API more consistent * log failed connection attempt * agent string can't contain spaces * add websock topic (#83) * style Co-authored-by: Tanguy Cizain <tanguycizain@gmail.com>
This commit is contained in:
parent
fec0f2bac1
commit
06ae75cf7f
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"]
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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!")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue