diff --git a/.gitignore b/.gitignore index f1d1222..83233aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,18 @@ -/tests/* -!/tests/*.nim -!/tests/*.cfg +* +!**/ +!*.* +*.out +.DS_Store +!.gitattributes +!.gitignore +!readme.md +!.gitkeep +!*.nim +!*.nims +!*.nimble +!*.h +!*.css +!*.html +*.exe +!*/ +nimbledeps diff --git a/src/httpbeast.nim b/src/httpbeast.nim index 5b4c9d4..5f3bdaf 100644 --- a/src/httpbeast.nim +++ b/src/httpbeast.nim @@ -51,6 +51,8 @@ type OnRequest* = proc (req: Request): Future[void] {.gcsafe.} + Startup = proc () {.closure, gcsafe.} + Settings* = object port*: Port bindAddr*: string @@ -68,15 +70,23 @@ type ## 4096 for Linux/AMD64 and 128 for others. ## * listen(2) Linux manual page: https://www.man7.org/linux/man-pages/man2/listen.2.html ## * SYN packet handling int the wild: https://blog.cloudflare.com/syn-packet-handling-in-the-wild/ + startup: Startup + ## An optional callback can be provided to execute at the beginning of + ## the `eventLoop` function for initializing thread variables or performing other related tasks. HttpBeastDefect* = ref object of Defect const serverInfo = "HttpBeast" +proc doNothing(): Startup {.gcsafe.} = + result = proc () {.closure, gcsafe.} = + discard + proc initSettings*(port: Port = Port(8080), bindAddr: string = "", numThreads: int = 0, + startup: Startup = doNothing(), domain = Domain.AF_INET, reusePort = true, listenBacklog = SOMAXCONN): Settings = @@ -88,6 +98,7 @@ proc initSettings*(port: Port = Port(8080), loggers: getHandlers(), reusePort: reusePort, listenBacklog: listenBacklog, + startup: startup ) proc initData(fdKind: FdKind, ip = ""): Data = @@ -333,6 +344,9 @@ proc eventLoop( ) = let (onRequest, settings, isMainThread) = params + if settings.startup != nil: + settings.startup() + if not isMainThread: # We are on a new thread. Re-add the loggers from the main thread. for logger in settings.loggers: diff --git a/tests/startup.ini b/tests/startup.ini new file mode 100644 index 0000000..5de2e31 --- /dev/null +++ b/tests/startup.ini @@ -0,0 +1,7 @@ +charset = "utf-8" +[Package] +name = "hello" +--threads:on +[Author] +name = "nim-lang" +website = "nim-lang.org" diff --git a/tests/startup.nim b/tests/startup.nim new file mode 100644 index 0000000..83a5ba7 --- /dev/null +++ b/tests/startup.nim @@ -0,0 +1,41 @@ +import os, options, asyncdispatch, parsecfg, strutils, streams +import httpbeast + +const CurDir = currentSourcePath.parentDir + +var threadsOn {.threadvar.}: bool +var name {.threadvar.}: string + +proc onRequest(req: Request): Future[void] = + if req.httpMethod == some(HttpGet): + case req.path.get() + of "/": + req.send("name:$#,threads:$#." % [name, $threadsOn]) + else: + req.send(Http404) + +var startup = proc () = + let configFile = CurDir / "startup.ini" + var f = newFileStream(configFile, fmRead) + assert f != nil, "cannot open " & configFile + var p: CfgParser + var section: string + open(p, f, configFile) + while true: + var e = next(p) + case e.kind + of cfgEof: break + of cfgSectionStart: ## a `[section]` has been parsed + section = e.section + of cfgKeyValuePair: + if section == "Package" and e.key == "name": + name = e.value + of cfgOption: + if e.key == "threads": + if e.value == "on": + threadsOn = true + of cfgError: + echo e.msg + close(p) + +run(onRequest, initSettings(startup = startup))