mirror of https://github.com/waku-org/nwaku.git
194 lines
6.7 KiB
Nim
194 lines
6.7 KiB
Nim
{.push raises: [].}
|
|
|
|
import net, tables
|
|
import presto
|
|
import
|
|
waku/waku_node,
|
|
waku/discovery/waku_discv5,
|
|
waku/factory/external_config,
|
|
waku/waku_api/message_cache,
|
|
waku/waku_api/handlers,
|
|
waku/waku_api/rest/server,
|
|
waku/waku_api/rest/debug/handlers as rest_debug_api,
|
|
waku/waku_api/rest/relay/handlers as rest_relay_api,
|
|
waku/waku_api/rest/filter/handlers as rest_filter_api,
|
|
waku/waku_api/rest/lightpush/handlers as rest_lightpush_api,
|
|
waku/waku_api/rest/store/handlers as rest_store_api,
|
|
waku/waku_api/rest/legacy_store/handlers as rest_store_legacy_api,
|
|
waku/waku_api/rest/health/handlers as rest_health_api,
|
|
waku/waku_api/rest/admin/handlers as rest_admin_api,
|
|
waku/waku_core/topics
|
|
|
|
## Monitoring and external interfaces
|
|
|
|
# Used to register api endpoints that are not currently installed as keys,
|
|
# values are holding error messages to be returned to the client
|
|
# NOTE: {.threadvar.} is used to make the global variable GC safe for the closure uses it
|
|
# It will always be called from main thread anyway.
|
|
# Ref: https://nim-lang.org/docs/manual.html#threads-gc-safety
|
|
var restServerNotInstalledTab {.threadvar.}: TableRef[string, string]
|
|
restServerNotInstalledTab = newTable[string, string]()
|
|
|
|
proc startRestServerEsentials*(
|
|
nodeHealthMonitor: WakuNodeHealthMonitor, conf: WakuNodeConf
|
|
): Result[WakuRestServerRef, string] =
|
|
if not conf.rest:
|
|
return ok(nil)
|
|
|
|
let requestErrorHandler: RestRequestErrorHandler = proc(
|
|
error: RestRequestError, request: HttpRequestRef
|
|
): Future[HttpResponseRef] {.async: (raises: [CancelledError]).} =
|
|
try:
|
|
case error
|
|
of RestRequestError.Invalid:
|
|
return await request.respond(Http400, "Invalid request", HttpTable.init())
|
|
of RestRequestError.NotFound:
|
|
let paths = request.rawPath.split("/")
|
|
let rootPath =
|
|
if len(paths) > 1:
|
|
paths[1]
|
|
else:
|
|
""
|
|
restServerNotInstalledTab[].withValue(rootPath, errMsg):
|
|
return await request.respond(Http404, errMsg[], HttpTable.init())
|
|
do:
|
|
return await request.respond(
|
|
Http400,
|
|
"Bad request initiated. Invalid path or method used.",
|
|
HttpTable.init(),
|
|
)
|
|
of RestRequestError.InvalidContentBody:
|
|
return await request.respond(Http400, "Invalid content body", HttpTable.init())
|
|
of RestRequestError.InvalidContentType:
|
|
return await request.respond(Http400, "Invalid content type", HttpTable.init())
|
|
of RestRequestError.Unexpected:
|
|
return defaultResponse()
|
|
except HttpWriteError:
|
|
error "Failed to write response to client", error = getCurrentExceptionMsg()
|
|
discard
|
|
|
|
return defaultResponse()
|
|
|
|
let allowedOrigin =
|
|
if len(conf.restAllowOrigin) > 0:
|
|
some(conf.restAllowOrigin.join(","))
|
|
else:
|
|
none(string)
|
|
|
|
let address = conf.restAddress
|
|
let port = Port(conf.restPort + conf.portsShift)
|
|
let server =
|
|
?newRestHttpServer(
|
|
address,
|
|
port,
|
|
allowedOrigin = allowedOrigin,
|
|
requestErrorHandler = requestErrorHandler,
|
|
)
|
|
|
|
## Health REST API
|
|
installHealthApiHandler(server.router, nodeHealthMonitor)
|
|
|
|
restServerNotInstalledTab["admin"] =
|
|
"/admin endpoints are not available while initializing."
|
|
restServerNotInstalledTab["debug"] =
|
|
"/debug endpoints are not available while initializing."
|
|
restServerNotInstalledTab["relay"] =
|
|
"/relay endpoints are not available while initializing."
|
|
restServerNotInstalledTab["filter"] =
|
|
"/filter endpoints are not available while initializing."
|
|
restServerNotInstalledTab["lightpush"] =
|
|
"/lightpush endpoints are not available while initializing."
|
|
restServerNotInstalledTab["store"] =
|
|
"/store endpoints are not available while initializing."
|
|
|
|
server.start()
|
|
info "Starting REST HTTP server", url = "http://" & $address & ":" & $port & "/"
|
|
|
|
ok(server)
|
|
|
|
proc startRestServerProtocolSupport*(
|
|
restServer: WakuRestServerRef,
|
|
node: WakuNode,
|
|
wakuDiscv5: WakuDiscoveryV5,
|
|
conf: WakuNodeConf,
|
|
): Result[void, string] =
|
|
if not conf.rest:
|
|
return ok()
|
|
|
|
var router = restServer.router
|
|
## Admin REST API
|
|
if conf.restAdmin:
|
|
installAdminApiHandlers(router, node)
|
|
else:
|
|
restServerNotInstalledTab["admin"] =
|
|
"/admin endpoints are not available. Please check your configuration: --rest-admin=true"
|
|
|
|
## Debug REST API
|
|
installDebugApiHandlers(router, node)
|
|
|
|
## Relay REST API
|
|
if conf.relay:
|
|
let cache = MessageCache.init(int(conf.restRelayCacheCapacity))
|
|
|
|
let handler = messageCacheHandler(cache)
|
|
|
|
for shard in conf.shards:
|
|
let pubsubTopic = $RelayShard(clusterId: conf.clusterId, shardId: shard)
|
|
cache.pubsubSubscribe(pubsubTopic)
|
|
node.subscribe((kind: PubsubSub, topic: pubsubTopic), some(handler))
|
|
|
|
for contentTopic in conf.contentTopics:
|
|
cache.contentSubscribe(contentTopic)
|
|
node.subscribe((kind: ContentSub, topic: contentTopic), some(handler))
|
|
|
|
installRelayApiHandlers(router, node, cache)
|
|
else:
|
|
restServerNotInstalledTab["relay"] =
|
|
"/relay endpoints are not available. Please check your configuration: --relay"
|
|
|
|
## Filter REST API
|
|
if conf.filternode != "" and node.wakuFilterClient != nil:
|
|
let filterCache = MessageCache.init()
|
|
|
|
let filterDiscoHandler =
|
|
if not wakuDiscv5.isNil():
|
|
some(defaultDiscoveryHandler(wakuDiscv5, Filter))
|
|
else:
|
|
none(DiscoveryHandler)
|
|
|
|
rest_filter_api.installFilterRestApiHandlers(
|
|
router, node, filterCache, filterDiscoHandler
|
|
)
|
|
else:
|
|
restServerNotInstalledTab["filter"] =
|
|
"/filter endpoints are not available. Please check your configuration: --filternode"
|
|
|
|
## Store REST API
|
|
let storeDiscoHandler =
|
|
if not wakuDiscv5.isNil():
|
|
some(defaultDiscoveryHandler(wakuDiscv5, Store))
|
|
else:
|
|
none(DiscoveryHandler)
|
|
|
|
rest_store_api.installStoreApiHandlers(router, node, storeDiscoHandler)
|
|
rest_store_legacy_api.installStoreApiHandlers(router, node, storeDiscoHandler)
|
|
|
|
## Light push API
|
|
## Install it either if lightpushnode (lightpush service node) is configured and client is mounted)
|
|
## or install it to be used with self-hosted lightpush service
|
|
if (conf.lightpushnode != "" and node.wakuLightpushClient != nil) or
|
|
(conf.lightpush and node.wakuLightPush != nil and node.wakuRelay != nil):
|
|
let lightDiscoHandler =
|
|
if not wakuDiscv5.isNil():
|
|
some(defaultDiscoveryHandler(wakuDiscv5, Lightpush))
|
|
else:
|
|
none(DiscoveryHandler)
|
|
|
|
rest_lightpush_api.installLightPushRequestHandler(router, node, lightDiscoHandler)
|
|
else:
|
|
restServerNotInstalledTab["lightpush"] =
|
|
"/lightpush endpoints are not available. Please check your configuration: --lightpushnode"
|
|
|
|
info "REST services are installed"
|
|
return ok()
|