align nim-websock support with news

To allow switching between `news` and `nim-websock` in `nimbus-eth2`,
add support for the missing CORS and JWT authorization headers to the
`nim-websock` backend. Also transition from `StringTableRef` to
`HttpTable` to properly support multiple instances of same header name.
This commit is contained in:
Etan Kissling 2022-09-01 13:14:07 +02:00 committed by andri lim
parent 32ba2d16b9
commit c8cbe08de7

View File

@ -1,6 +1,5 @@
import import
std/[strtabs, tables], pkg/[chronos, chronos/apps/http/httptable, chronicles],
pkg/[chronos, chronicles],
stew/byteutils, stew/byteutils,
../client, ./config ../client, ./config
@ -103,42 +102,60 @@ proc processData(client: RpcWebSocketClient) {.async.} =
if not client.onDisconnect.isNil: if not client.onDisconnect.isNil:
client.onDisconnect() client.onDisconnect()
proc addExtraHeaders(
headers: var HttpTable,
client: RpcWebSocketClient,
extraHeaders: HttpTable) =
# Apply client instance overrides
if client.getHeaders != nil:
for header in client.getHeaders():
headers.add(header[0], header[1])
# Apply call specific overrides
for header in extraHeaders.stringItems:
headers.add(header.key, header.value)
# Apply default origin
discard headers.hasKeyOrPut("Origin", "http://localhost")
when useNews: when useNews:
func toStringTable(headersTable: HttpTable): StringTableRef =
let res = newStringTable(modeCaseInsensitive)
for header in headersTable:
res[header.key] = header.value.join(",")
res
proc connect*( proc connect*(
client: RpcWebSocketClient, client: RpcWebSocketClient,
uri: string, uri: string,
headers: StringTableRef = nil, extraHeaders: HttpTable = default(HttpTable),
compression = false) {.async.} = compression = false) {.async.} =
if compression: if compression:
warn "compression is not supported with the news back-end" warn "compression is not supported with the news back-end"
var headers = headers var headers = HttpTable.init()
if headers.isNil: headers.addExtraHeaders(client, extraHeaders)
headers = newStringTable({"Origin": "http://localhost"}) client.transport = await newWebSocket(uri, headers.toStringTable())
elif "Origin" notin headers:
# TODO: This is a hack, because the table might be case sensitive. Ideally strtabs module has
# to be extended with case insensitive accessors.
headers["Origin"] = "http://localhost"
if not isNil(client.getHeaders):
for header in client.getHeaders():
headers[header[0]] = header[1]
client.transport = await newWebSocket(uri, headers)
client.uri = uri client.uri = uri
client.loop = processData(client) client.loop = processData(client)
else: else:
proc connect*( proc connect*(
client: RpcWebSocketClient, uri: string, client: RpcWebSocketClient,
uri: string,
extraHeaders: HttpTable = default(HttpTable),
compression = false, compression = false,
hooks: seq[Hook] = @[], hooks: seq[Hook] = @[],
flags: set[TLSFlags] = {NoVerifyHost, NoVerifyServerName}) {.async.} = flags: set[TLSFlags] = {NoVerifyHost, NoVerifyServerName}) {.async.} =
proc headersHook(ctx: Hook, headers: var HttpTable): Result[void, string] =
headers.addExtraHeaders(client, extraHeaders)
ok()
var ext: seq[ExtFactory] = if compression: @[deflateFactory()] var ext: seq[ExtFactory] = if compression: @[deflateFactory()]
else: @[] else: @[]
let uri = parseUri(uri) let uri = parseUri(uri)
let ws = await WebSocket.connect( let ws = await WebSocket.connect(
uri=uri, uri=uri,
factories=ext, factories=ext,
hooks=hooks, hooks=hooks & Hook(append: headersHook),
flags=flags flags=flags)
)
client.transport = ws client.transport = ws
client.uri = uri client.uri = uri
client.loop = processData(client) client.loop = processData(client)