Mercurial > code > home > repos > homeauto
view service/rfid_pn532/graphserver.nim @ 507:f3c1d2e7c5df
add missing files for the record
Ignore-this: 8541c95ef1644cf85b311259602d2892
author | drewp@bigasterisk.com |
---|---|
date | Sun, 21 Apr 2019 03:28:21 -0700 |
parents | 56af0ca2db10 |
children |
line wrap: on
line source
import asynchttpserver, asyncdispatch, asyncnet, strtabs, sequtils, times, os, strutils, strformat import sets import rdf import rdf_nodes type GraphServer* = ref object of RootObj port*: int clients: seq[AsyncSocket] previousUpdateTime: int httpServer: AsyncHttpServer serverReady: Future[void] graph: Graph proc ssePayload(eventType: string, body: string): string = eventType & ": " & body & "\n\n" proc sendEvent(client: AsyncSocket, eventType: string, body: string) {.async.} = if not client.isClosed(): asyncCheck client.send(ssePayload(eventType, body)) proc sendEventToAll(self: GraphServer, eventType: string, body: string) {.async.} = let payload = ssePayload(eventType, body) for client in self.clients: if not client.isClosed(): asyncCheck client.send(payload) proc handleCORS(req: Request) {.async.} = await req.respond(Http204, "", newHttpHeaders({ "Access-Control-Allow-Origin": "*", "Connection": "close"})) proc handle404(req: Request) {.async.} = let headers = newHttpHeaders({"Content-Type": "text/plain", "Connection": "close"}) await req.respond(Http404, "File not found", headers) req.client.close() proc handleSSE(self: GraphServer, req: Request) {.async.} = let headers = newHttpHeaders({"Content-Type": "text/event-stream", "Access-Control-Allow-Origin": "*", "Cache-Control": "no-cache", "Connection": "keep-alive"}) await req.client.send("HTTP/1.1 200 OK\c\L") await req.sendHeaders(headers) await req.client.send("\c\L:ok\n\n") await sendEvent(req.client, "fullGraph", Patch(addQuads: self.graph.stmts).toJson()) self.clients.add(req.client) proc handleConnections(self: GraphServer, req: Request) {.async.} = let clientCount = self.clients.len let headers = newHttpHeaders({"Content-Type": "text/plain", "Access-Control-Allow-Origin": "*", "Cache-Control": "no-cache", "Connection": "close"}) await req.respond(Http200, $clientCount, headers) req.client.close() proc handleGraph(self: GraphServer, req: Request) {.async.} = await req.respond(Http200, self.graph.toNquads(), newHttpHeaders({ "Content-Type": "application/n-quads", })) req.client.close() proc applyPatch*(self: GraphServer, p: Patch) {.async.} = self.graph.applyPatch(p) let body = p.toJson() echo "emitpatch " & body asyncCheck self.sendEventToAll("patch", body) # Replace graph contents. proc setGraph*(self: GraphServer, quads: HashSet[Quad]) {.async.} = let p = Patch(addQuads: quads - self.graph.stmts, delQuads: self.graph.stmts - quads) asyncCheck self.graph.applyPatch(p) proc handleCurrentGraph(self: GraphServer, req: Request) {.async.} = let quad = HashSet[Quad]([]) self.setGraph(quads) proc requestCallback(self: GraphServer, req: Request) {.async.} = if req.reqMethod == HttpOptions: asyncCheck handleCORS(req) else: case req.url.path of "/connections": asyncCheck self.handleConnections(req) of "/graph": asyncCheck self.handleGraph(req) of "/graph/events": asyncCheck self.handleSSE(req) of "/currentGraph": asyncCheck self.handleCurrentGraph(req) else: asyncCheck handle404(req) proc newGraphServer*(port: int): GraphServer = new(result) result.port = port result.previousUpdateTime = toInt(epochTime() * 1000) result.graph = initGraph() result.httpServer = newAsyncHttpServer(true) let self = result # https://github.com/dom96/nim-in-action-code/issues/6#issuecomment-446956468 has been applied to ./nim-0.19.4/lib/pure/asynchttpserver.nim proc handler(req: Request): Future[void] {.async.} = asyncCheck self.requestCallback(req) self.serverReady = self.httpServer.serve(Port(self.port), handler, address="0.0.0.0") asyncCheck self.serverReady echo "Listening on " & $self.port proc checkClients(self: GraphServer) = self.clients = self.clients.filterIt(not it.isClosed()) proc pingClients(self: GraphServer) {.async.} = let currentTime = toInt(epochTime() * 1000) if currentTime - self.previousUpdateTime < 1000: return asyncCheck self.sendEventToAll("data", $currentTime) self.previousUpdateTime = toInt(epochTime() * 1000) proc run*(self: GraphServer) = while true: self.checkClients() asyncCheck self.pingClients() poll() let server = newGraphServer(port = 10012) server.run()