2024-02-29 09:48:14 +01:00
|
|
|
{.used.}
|
|
|
|
|
|
|
|
|
|
import
|
|
|
|
|
testutils/unittests,
|
|
|
|
|
presto,
|
|
|
|
|
presto/client as presto_client,
|
|
|
|
|
libp2p/peerinfo,
|
|
|
|
|
libp2p/multiaddress,
|
|
|
|
|
libp2p/crypto/crypto
|
|
|
|
|
import
|
2024-07-06 03:33:38 +05:30
|
|
|
waku/[
|
|
|
|
|
waku_node,
|
|
|
|
|
node/waku_node as waku_node2,
|
2025-11-15 23:31:09 +01:00
|
|
|
rest_api/endpoint/server,
|
|
|
|
|
rest_api/endpoint/debug/handlers as debug_rest_interface,
|
2024-07-06 03:33:38 +05:30
|
|
|
],
|
2024-02-29 09:48:14 +01:00
|
|
|
../testlib/common,
|
|
|
|
|
../testlib/wakucore,
|
|
|
|
|
../testlib/wakunode
|
|
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
type TestResponseTuple = tuple[status: int, data: string, headers: HttpTable]
|
2024-02-29 09:48:14 +01:00
|
|
|
|
|
|
|
|
proc testWakuNode(): WakuNode =
|
|
|
|
|
let
|
|
|
|
|
privkey = crypto.PrivateKey.random(Secp256k1, rng[]).tryGet()
|
|
|
|
|
bindIp = parseIpAddress("0.0.0.0")
|
|
|
|
|
extIp = parseIpAddress("127.0.0.1")
|
2024-06-12 15:07:33 +02:00
|
|
|
port = Port(0)
|
2024-02-29 09:48:14 +01:00
|
|
|
|
|
|
|
|
newTestWakuNode(privkey, bindIp, port, some(extIp), some(port))
|
|
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
proc fetchWithHeader(
|
|
|
|
|
request: HttpClientRequestRef
|
|
|
|
|
): Future[TestResponseTuple] {.async: (raises: [CancelledError, HttpError]).} =
|
2024-02-29 09:48:14 +01:00
|
|
|
var response: HttpClientResponseRef
|
|
|
|
|
try:
|
|
|
|
|
response = await request.send()
|
|
|
|
|
let buffer = await response.getBodyBytes()
|
|
|
|
|
let status = response.status
|
|
|
|
|
let headers = response.headers
|
|
|
|
|
await response.closeWait()
|
|
|
|
|
response = nil
|
|
|
|
|
return (status, buffer.bytesToString(), headers)
|
|
|
|
|
except HttpError as exc:
|
2024-03-16 00:08:47 +01:00
|
|
|
if not (isNil(response)):
|
|
|
|
|
await response.closeWait()
|
2024-02-29 09:48:14 +01:00
|
|
|
assert false
|
|
|
|
|
except CancelledError as exc:
|
2024-03-16 00:08:47 +01:00
|
|
|
if not (isNil(response)):
|
|
|
|
|
await response.closeWait()
|
2024-02-29 09:48:14 +01:00
|
|
|
assert false
|
|
|
|
|
|
|
|
|
|
proc issueRequest(
|
2024-03-16 00:08:47 +01:00
|
|
|
address: HttpAddress, reqOrigin: Option[string] = none(string)
|
|
|
|
|
): Future[TestResponseTuple] {.async.} =
|
2024-02-29 09:48:14 +01:00
|
|
|
var
|
|
|
|
|
session = HttpSessionRef.new({HttpClientFlag.Http11Pipeline})
|
|
|
|
|
data: TestResponseTuple
|
|
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
var originHeader: seq[HttpHeaderTuple]
|
2024-02-29 09:48:14 +01:00
|
|
|
if reqOrigin.isSome():
|
|
|
|
|
originHeader.insert(("Origin", reqOrigin.get()))
|
|
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
var request = HttpClientRequestRef.new(
|
|
|
|
|
session, address, version = HttpVersion11, headers = originHeader
|
|
|
|
|
)
|
2024-02-29 09:48:14 +01:00
|
|
|
try:
|
|
|
|
|
data = await request.fetchWithHeader()
|
|
|
|
|
finally:
|
|
|
|
|
await request.closeWait()
|
|
|
|
|
return data
|
|
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
proc checkResponse(
|
|
|
|
|
response: TestResponseTuple, expectedStatus: int, expectedOrigin: Option[string]
|
|
|
|
|
): bool =
|
2024-02-29 09:48:14 +01:00
|
|
|
if response.status != expectedStatus:
|
2024-03-16 00:08:47 +01:00
|
|
|
echo(
|
|
|
|
|
" -> check failed: expected status" & $expectedStatus & " got " & $response.status
|
|
|
|
|
)
|
2024-02-29 09:48:14 +01:00
|
|
|
return false
|
|
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
if not (
|
|
|
|
|
expectedOrigin.isNone() or (
|
|
|
|
|
expectedOrigin.isSome() and
|
|
|
|
|
response.headers.contains("Access-Control-Allow-Origin") and
|
|
|
|
|
response.headers.getLastString("Access-Control-Allow-Origin") ==
|
2024-06-12 15:07:33 +02:00
|
|
|
expectedOrigin.get() and response.headers.contains("Access-Control-Allow-Headers") and
|
2024-04-18 18:29:50 +08:00
|
|
|
response.headers.getLastString("Access-Control-Allow-Headers") == "Content-Type"
|
2024-03-16 00:08:47 +01:00
|
|
|
)
|
|
|
|
|
):
|
|
|
|
|
echo(
|
|
|
|
|
" -> check failed: expected origin " & $expectedOrigin & " got " &
|
|
|
|
|
response.headers.getLastString("Access-Control-Allow-Origin")
|
|
|
|
|
)
|
2024-02-29 09:48:14 +01:00
|
|
|
return false
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
|
|
suite "Waku v2 REST API CORS Handling":
|
|
|
|
|
asyncTest "AllowedOrigin matches":
|
|
|
|
|
# Given
|
|
|
|
|
let node = testWakuNode()
|
|
|
|
|
await node.start()
|
2025-05-05 22:57:20 +02:00
|
|
|
(await node.mountRelay()).isOkOr:
|
|
|
|
|
assert false, "Failed to mount relay"
|
2024-02-29 09:48:14 +01:00
|
|
|
|
2024-06-12 15:07:33 +02:00
|
|
|
var restPort = Port(0)
|
2024-02-29 09:48:14 +01:00
|
|
|
let restAddress = parseIpAddress("0.0.0.0")
|
2024-03-16 00:08:47 +01:00
|
|
|
let restServer = WakuRestServerRef
|
|
|
|
|
.init(
|
|
|
|
|
restAddress,
|
|
|
|
|
restPort,
|
|
|
|
|
allowedOrigin =
|
|
|
|
|
some("test.net:1234,https://localhost:*,http://127.0.0.1:?8,?waku*.net:*80*"),
|
|
|
|
|
)
|
|
|
|
|
.tryGet()
|
2024-06-12 15:07:33 +02:00
|
|
|
restPort = restServer.httpServer.address.port # update with bound port for client use
|
2024-02-29 09:48:14 +01:00
|
|
|
|
|
|
|
|
installDebugApiHandlers(restServer.router, node)
|
|
|
|
|
restServer.start()
|
|
|
|
|
|
|
|
|
|
let srvAddr = restServer.localAddress()
|
|
|
|
|
let ha = getAddress(srvAddr, HttpClientScheme.NonSecure, "/debug/v1/info")
|
|
|
|
|
|
|
|
|
|
# When
|
|
|
|
|
var response = await issueRequest(ha, some("http://test.net:1234"))
|
|
|
|
|
check checkResponse(response, 200, some("http://test.net:1234"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("https://test.net:1234"))
|
|
|
|
|
check checkResponse(response, 200, some("https://test.net:1234"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("https://localhost:8080"))
|
|
|
|
|
check checkResponse(response, 200, some("https://localhost:8080"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("https://localhost:80"))
|
|
|
|
|
check checkResponse(response, 200, some("https://localhost:80"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://127.0.0.1:78"))
|
|
|
|
|
check checkResponse(response, 200, some("http://127.0.0.1:78"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://wakuTHE.net:8078"))
|
|
|
|
|
check checkResponse(response, 200, some("http://wakuTHE.net:8078"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://nwaku.main.net:1980"))
|
|
|
|
|
check checkResponse(response, 200, some("http://nwaku.main.net:1980"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://nwaku.main.net:80"))
|
|
|
|
|
check checkResponse(response, 200, some("http://nwaku.main.net:80"))
|
|
|
|
|
|
|
|
|
|
await restServer.stop()
|
|
|
|
|
await restServer.closeWait()
|
|
|
|
|
await node.stop()
|
|
|
|
|
|
|
|
|
|
asyncTest "AllowedOrigin reject":
|
|
|
|
|
# Given
|
|
|
|
|
let node = testWakuNode()
|
|
|
|
|
await node.start()
|
2025-05-05 22:57:20 +02:00
|
|
|
(await node.mountRelay()).isOkOr:
|
|
|
|
|
assert false, "Failed to mount relay"
|
2024-02-29 09:48:14 +01:00
|
|
|
|
2024-06-12 15:07:33 +02:00
|
|
|
var restPort = Port(0)
|
2024-02-29 09:48:14 +01:00
|
|
|
let restAddress = parseIpAddress("0.0.0.0")
|
2024-03-16 00:08:47 +01:00
|
|
|
let restServer = WakuRestServerRef
|
|
|
|
|
.init(
|
|
|
|
|
restAddress,
|
|
|
|
|
restPort,
|
|
|
|
|
allowedOrigin =
|
|
|
|
|
some("test.net:1234,https://localhost:*,http://127.0.0.1:?8,?waku*.net:*80*"),
|
|
|
|
|
)
|
|
|
|
|
.tryGet()
|
2024-06-12 15:07:33 +02:00
|
|
|
restPort = restServer.httpServer.address.port # update with bound port for client use
|
2024-02-29 09:48:14 +01:00
|
|
|
|
|
|
|
|
installDebugApiHandlers(restServer.router, node)
|
|
|
|
|
restServer.start()
|
|
|
|
|
|
|
|
|
|
let srvAddr = restServer.localAddress()
|
|
|
|
|
let ha = getAddress(srvAddr, HttpClientScheme.NonSecure, "/debug/v1/info")
|
|
|
|
|
|
|
|
|
|
# When
|
|
|
|
|
var response = await issueRequest(ha, some("http://test.net:12334"))
|
|
|
|
|
check checkResponse(response, 403, none(string))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://test.net:12345"))
|
|
|
|
|
check checkResponse(response, 403, none(string))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("xhttp://test.net:1234"))
|
|
|
|
|
check checkResponse(response, 403, none(string))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("https://xtest.net:1234"))
|
|
|
|
|
check checkResponse(response, 403, none(string))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://localhost:8080"))
|
|
|
|
|
check checkResponse(response, 403, none(string))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("https://127.0.0.1:78"))
|
|
|
|
|
check checkResponse(response, 403, none(string))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://127.0.0.1:89"))
|
|
|
|
|
check checkResponse(response, 403, none(string))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://the.waku.net:8078"))
|
|
|
|
|
check checkResponse(response, 403, none(string))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://nwaku.main.net:1900"))
|
|
|
|
|
check checkResponse(response, 403, none(string))
|
|
|
|
|
|
|
|
|
|
await restServer.stop()
|
|
|
|
|
await restServer.closeWait()
|
|
|
|
|
await node.stop()
|
|
|
|
|
|
|
|
|
|
asyncTest "AllowedOrigin allmatches":
|
|
|
|
|
# Given
|
|
|
|
|
let node = testWakuNode()
|
|
|
|
|
await node.start()
|
2025-05-05 22:57:20 +02:00
|
|
|
(await node.mountRelay()).isOkOr:
|
|
|
|
|
assert false, "Failed to mount relay"
|
2024-02-29 09:48:14 +01:00
|
|
|
|
2024-06-12 15:07:33 +02:00
|
|
|
var restPort = Port(0)
|
2024-02-29 09:48:14 +01:00
|
|
|
let restAddress = parseIpAddress("0.0.0.0")
|
2024-03-16 00:08:47 +01:00
|
|
|
let restServer =
|
|
|
|
|
WakuRestServerRef.init(restAddress, restPort, allowedOrigin = some("*")).tryGet()
|
2024-06-12 15:07:33 +02:00
|
|
|
restPort = restServer.httpServer.address.port # update with bound port for client use
|
2024-02-29 09:48:14 +01:00
|
|
|
|
|
|
|
|
installDebugApiHandlers(restServer.router, node)
|
|
|
|
|
restServer.start()
|
|
|
|
|
|
|
|
|
|
let srvAddr = restServer.localAddress()
|
|
|
|
|
let ha = getAddress(srvAddr, HttpClientScheme.NonSecure, "/debug/v1/info")
|
|
|
|
|
|
|
|
|
|
# When
|
|
|
|
|
var response = await issueRequest(ha, some("http://test.net:1234"))
|
|
|
|
|
check checkResponse(response, 200, some("*"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("https://test.net:1234"))
|
|
|
|
|
check checkResponse(response, 200, some("*"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("https://localhost:8080"))
|
|
|
|
|
check checkResponse(response, 200, some("*"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("https://localhost:80"))
|
|
|
|
|
check checkResponse(response, 200, some("*"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://127.0.0.1:78"))
|
|
|
|
|
check checkResponse(response, 200, some("*"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://wakuTHE.net:8078"))
|
|
|
|
|
check checkResponse(response, 200, some("*"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://nwaku.main.net:1980"))
|
|
|
|
|
check checkResponse(response, 200, some("*"))
|
|
|
|
|
|
|
|
|
|
response = await issueRequest(ha, some("http://nwaku.main.net:80"))
|
|
|
|
|
check checkResponse(response, 200, some("*"))
|
|
|
|
|
|
|
|
|
|
await restServer.stop()
|
|
|
|
|
await restServer.closeWait()
|
|
|
|
|
await node.stop()
|
|
|
|
|
|
|
|
|
|
asyncTest "No origin goes through":
|
|
|
|
|
# Given
|
|
|
|
|
let node = testWakuNode()
|
|
|
|
|
await node.start()
|
2025-05-05 22:57:20 +02:00
|
|
|
(await node.mountRelay()).isOkOr:
|
|
|
|
|
assert false, "Failed to mount relay"
|
2024-02-29 09:48:14 +01:00
|
|
|
|
2024-06-12 15:07:33 +02:00
|
|
|
var restPort = Port(0)
|
2024-02-29 09:48:14 +01:00
|
|
|
let restAddress = parseIpAddress("0.0.0.0")
|
2024-03-16 00:08:47 +01:00
|
|
|
let restServer = WakuRestServerRef
|
|
|
|
|
.init(
|
|
|
|
|
restAddress,
|
|
|
|
|
restPort,
|
|
|
|
|
allowedOrigin =
|
|
|
|
|
some("test.net:1234,https://localhost:*,http://127.0.0.1:?8,?waku*.net:*80*"),
|
|
|
|
|
)
|
|
|
|
|
.tryGet()
|
2024-06-12 15:07:33 +02:00
|
|
|
restPort = restServer.httpServer.address.port # update with bound port for client use
|
2024-02-29 09:48:14 +01:00
|
|
|
|
|
|
|
|
installDebugApiHandlers(restServer.router, node)
|
|
|
|
|
restServer.start()
|
|
|
|
|
|
|
|
|
|
let srvAddr = restServer.localAddress()
|
|
|
|
|
let ha = getAddress(srvAddr, HttpClientScheme.NonSecure, "/debug/v1/info")
|
|
|
|
|
|
|
|
|
|
# When
|
|
|
|
|
var response = await issueRequest(ha, none(string))
|
|
|
|
|
check checkResponse(response, 200, none(string))
|
|
|
|
|
|
|
|
|
|
await restServer.stop()
|
|
|
|
|
await restServer.closeWait()
|
|
|
|
|
await node.stop()
|