nim-websock/tests/testhooks.nim

204 lines
5.1 KiB
Nim

## nim-websock
## Copyright (c) 2021-2022 Status Research & Development GmbH
## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
## at your option.
## This file may not be copied, modified, or distributed except according to
## those terms.
import pkg/[
httputils,
chronos/unittest2/asynctests,
]
import ../websock/websock
import ./helpers
let address = initTAddress("127.0.0.1:8888")
type
TokenHook* = ref object of Hook
status: int
token: string
request: HttpRequest
proc clientAppendGoodToken(ctx: Hook, headers: var HttpTable):
Result[void, string] {.gcsafe, raises: [].} =
headers.add("auth-token", "good-token")
return ok()
proc clientAppendBadToken(ctx: Hook, headers: var HttpTable):
Result[void, string] {.gcsafe, raises: [].} =
headers.add("auth-token", "bad-token")
return ok()
proc clientVerify(ctx: Hook, headers: HttpTable):
Future[Result[void, string]] {.gcsafe, async: (raises: []).} =
var p = TokenHook(ctx)
p.token = headers.getString("auth-status")
return ok()
proc serverVerify(ctx: Hook, headers: HttpTable):
Future[Result[void, string]] {.gcsafe, async: (raises: []).} =
var p = TokenHook(ctx)
if headers.getString("auth-token") == "good-token":
p.status = 101
return ok()
proc serverAppend(ctx: Hook, headers: var HttpTable):
Result[void, string] {.gcsafe, raises: [].} =
var p = TokenHook(ctx)
if p.status == 101:
headers.add("auth-status", "accept")
else:
headers.add("auth-status", "reject")
p.status = 0
return ok()
proc goodClientHook(): Hook =
TokenHook(
append: clientAppendGoodToken,
verify: clientVerify
)
proc badClientHook(): Hook =
TokenHook(
append: clientAppendBadToken,
verify: clientVerify
)
proc serverHook(): Hook =
TokenHook(
append: serverAppend,
verify: serverVerify
)
proc serverVerifyWithCode(ctx: Hook, headers: HttpTable):
Future[Result[void, string]] {.gcsafe, async: (raises: []).} =
try:
var p = TokenHook(ctx)
if headers.getString("auth-token") == "good-token":
p.status = 101
return ok()
else:
await p.request.stream.writer.sendError(Http401)
return err("authentication error")
except CatchableError as exc:
return err(exc.msg)
proc serverHookWithCode(request: HttpRequest): Hook =
TokenHook(
append: serverAppend,
verify: serverVerifyWithCode,
request: request
)
suite "Test Hooks":
setup:
var
server: HttpServer
goodCP {.used.} = goodClientHook()
badCP {.used.} = badClientHook()
teardown:
if server != nil:
server.stop()
waitFor server.closeWait()
asyncTest "client with valid token":
proc handle(request: HttpRequest) {.async.} =
check request.uri.path == WSPath
let
server = WSServer.new()
discard await server.handleRequest(
request,
hooks = @[serverHook()]
)
server = createServer(
address = address,
handler = handle,
flags = {ReuseAddr})
let session = await WebSocket.connect(
host = initTAddress("127.0.0.1:8888"),
path = WSPath,
hooks = @[goodCP]
)
check TokenHook(goodCP).token == "accept"
await session.stream.closeWait()
asyncTest "client with bad token":
proc handle(request: HttpRequest) {.async.} =
check request.uri.path == WSPath
let
server = WSServer.new()
discard await server.handleRequest(
request,
hooks = @[serverHook()]
)
server = createServer(
address = address,
handler = handle,
flags = {ReuseAddr})
let session = await WebSocket.connect(
host = initTAddress("127.0.0.1:8888"),
path = WSPath,
hooks = @[badCP]
)
check TokenHook(badCP).token == "reject"
await session.stream.closeWait()
asyncTest "server hook with code get good client":
proc handle(request: HttpRequest) {.async.} =
check request.uri.path == WSPath
let
server = WSServer.new()
discard await server.handleRequest(
request,
hooks = @[serverHookWithCode(request)]
)
server = createServer(
address = address,
handler = handle,
flags = {ReuseAddr})
let session = await WebSocket.connect(
host = initTAddress("127.0.0.1:8888"),
path = WSPath,
hooks = @[goodCP]
)
check TokenHook(goodCP).token == "accept"
await session.stream.closeWait()
asyncTest "server hook with code get bad client":
proc handle(request: HttpRequest) {.async.} =
check request.uri.path == WSPath
let
server = WSServer.new()
discard await server.handleRequest(
request,
hooks = @[serverHookWithCode(request)]
)
server = createServer(
address = address,
handler = handle,
flags = {ReuseAddr})
expect WSFailedUpgradeError:
let session = await WebSocket.connect(
host = initTAddress("127.0.0.1:8888"),
path = WSPath,
hooks = @[badCP]
)
await session.stream.closeWait()