Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
67bc5e1
Docs: HTTP Server tutorial.
moigagoo Mar 12, 2026
4d1a331
Add docstrings for Fence types.
moigagoo Mar 30, 2026
7ec227b
Docs: Examples: Reorganize HTTP server examples to Nimble projects in…
moigagoo Mar 30, 2026
0cef820
Docs: Add shiftinclude an admonish preprocessors.
moigagoo Mar 30, 2026
2c3177c
Docs: Add admonish css.
moigagoo Mar 30, 2026
0ca53ac
Add API docs building for apps inside chronos.
moigagoo Mar 30, 2026
5eb3a0f
Docs: HTTP Server: Finalize chapter 1.
moigagoo Mar 30, 2026
64fcfaf
Docs: HTTP Server: Finalize intro.
moigagoo Mar 30, 2026
0793ebe
Docs: summary: Fix path to async_procs.md.
moigagoo Mar 30, 2026
e013152
Docs: HTTP Server: Finalize chapter 2.
moigagoo Mar 30, 2026
f4fded7
Docs: HTTP Server: Finalize chapter 3.
moigagoo Mar 30, 2026
a027bb6
CI: doc: Install mdbook-shiftinclude.
moigagoo Mar 30, 2026
c98f2da
Docs: HTTP Server: Finalize chapter 4.
moigagoo Mar 30, 2026
1b14ff6
Docs: HTTP Server: Finalize chapter 5.
moigagoo Mar 30, 2026
f1d5034
CI: Update required mdbook-open-on-gh version.
moigagoo Mar 30, 2026
38043cf
Merge branch 'master' into httpserver_tutorial
moigagoo Mar 30, 2026
853e3e8
Docs: HTTP Server: Fix incorrect info about HttpProcessCallback2 in C…
moigagoo Mar 31, 2026
7239b2c
Docs: http server: chapter 3,4: Replace mutating var with in-place tr…
moigagoo Apr 13, 2026
f60b11a
Docs: http server: chapter 3,4: Remove explicit returns.
moigagoo Apr 13, 2026
d9d0d03
Docs: http server: Use valueOr instead of explicit isErr checks.
moigagoo Apr 13, 2026
cb2e38a
Merge branch 'master' into httpserver_tutorial
moigagoo Apr 13, 2026
82b85bf
Docs: http server: Chapter 4: Add more info on middlewares.
moigagoo Apr 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/doc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ jobs:
cargo binstall mdbook@0.4.36 \
mdbook-toc@0.14.1 \
mdbook-open-on-gh@2.4.3 \
mdbook-admonish@1.14.0
mdbook-admonish@1.14.0 \
mdbook-shiftinclude@0.1.0

- uses: jiro4989/setup-nim-action@v1
with:
Expand Down
16 changes: 15 additions & 1 deletion chronos.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ proc run(args, path: string) =
build args, path
exec "build/" & path.splitPath[1]

proc tryExec(cmd: string) =
try:
exec cmd
except Exception as e:
echo e.msg

task examples, "Build examples":
# Build book examples
for file in listFiles("docs/examples"):
Expand Down Expand Up @@ -94,4 +100,12 @@ task test_libbacktrace, "test with libbacktrace":

task docs, "Generate API documentation":
exec "mdbook build docs"
exec nimc & " doc " & "--git.url:https://github.com/status-im/nim-chronos --git.commit:master --outdir:docs/book/api --project chronos"
tryExec nimc & " doc " &
"--git.url:https://github.com/status-im/nim-chronos --git.commit:master --outdir:docs/book/api --project chronos"

# Build the docs for modules that aren't part of the main module.
for item in walkDir("chronos/apps/http"):
if item.kind == pcFile and item.path.splitFile().ext == ".nim":
tryExec nimc & " doc " &
"--git.url:https://github.com/status-im/nim-chronos --git.commit:master --outdir:docs/book/api/chronos/apps/http " &
item.path
4 changes: 4 additions & 0 deletions chronos/apps/http/httpserver.nim
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ type
remote*: Opt[TransportAddress]

ConnectionFence* = Result[HttpConnectionRef, HttpProcessError]
## Result type that can contain either a valid ``HttpConnectionRef`` or an
## ``HttpProcessError``.
RequestFence* = Result[HttpRequestRef, HttpProcessError]
## Result type that can contain either a valid ``HttpRequestRef`` or an
## ``HttpProcessError``.

HttpRequestFlags* {.pure.} = enum
BoundBody, UnboundBody, MultipartForm, UrlencodedForm, ClientExpect
Expand Down
8 changes: 7 additions & 1 deletion docs/book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ max-level = 2
command = "mdbook-open-on-gh"
renderer = ["html"]

[preprocessor.admonish]
command = "mdbook-admonish"
assets_version = "3.0.1" # do not edit: managed by `mdbook-admonish install`

[preprocessor.shiftinclude]

[output.html]
git-repository-url = "https://github.com/status-im/nim-chronos/"
git-branch = "master"
additional-css = ["open-in.css"]
additional-css = ["./open-in.css", "./mdbook-admonish.css", '.\mdbook-admonish.css']
13 changes: 13 additions & 0 deletions docs/examples/http_server/chapter1/chapter1.nimble
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Package

version = "0.1.0"
author = "Status Research & Development GmbH"
description = "Chronos HTTP server tutorial example"
license = "Apache-2.0"
srcDir = "src"
bin = @["dashboard"]

# Dependencies

requires "nim >= 2.0.0"
requires "chronos"
41 changes: 41 additions & 0 deletions docs/examples/http_server/chapter1/src/dashboard.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# ANCHOR: all
# ANCHOR: import
import chronos/apps/http/httpserver
# ANCHOR_END: import

# ANCHOR: handler
proc handler(reqfence: RequestFence): Future[HttpResponseRef] {.async: (raises: [CancelledError]).} =
if reqfence.isErr():
return defaultResponse()

let request = reqfence.get()

try:
return await request.respond(Http200, "Hello, Chronos!")
except HttpWriteError:
return defaultResponse()
# ANCHOR_END: handler

# ANCHOR: main
proc main() {.async: (raises: [TransportAddressError, CancelledError]).} =
let
address = initTAddress("127.0.0.1:8080")
server = HttpServerRef.new(address, handler).valueOr:
echo "Unable to start HTTP server: " & error
return

server.start()
echo "HTTP server running on http://127.0.0.1:8080"

try:
await server.join()
finally:
await server.stop()
await server.closeWait()
# ANCHOR_END: main

# ANCHOR: run
when isMainModule:
waitFor main()
# ANCHOR_END: run
# ANCHOR_END: all
13 changes: 13 additions & 0 deletions docs/examples/http_server/chapter2/chapter2.nimble
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Package

version = "0.1.0"
author = "Status Research & Development GmbH"
description = "Chronos HTTP server tutorial example"
license = "Apache-2.0"
srcDir = "src"
bin = @["dashboard"]

# Dependencies

requires "nim >= 2.0.0"
requires "chronos"
45 changes: 45 additions & 0 deletions docs/examples/http_server/chapter2/src/dashboard.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# ANCHOR: all
import chronos/apps/http/httpserver

# ANCHOR: handler
proc handler(reqfence: RequestFence): Future[HttpResponseRef] {.async: (raises: [CancelledError]).} =
if reqfence.isErr():
return defaultResponse()

let request = reqfence.get()

# ANCHOR: routing
try:
case request.uri.path
of "/":
return await request.respond(Http200, "Welcome to the Status Dashboard!")
of "/status":
return await request.respond(Http200, "The server is operational.")
else:
return await request.respond(Http404, "Page not found.")
except HttpWriteError:
return defaultResponse()
# ANCHOR_END: routing
# ANCHOR_END: handler

# ANCHOR: main
proc main() {.async: (raises: [TransportAddressError, CancelledError]).} =
let
address = initTAddress("127.0.0.1:8080")
server = HttpServerRef.new(address, handler).valueOr:
echo "Unable to start HTTP server: " & error
return

server.start()
echo "HTTP server running on http://127.0.0.1:8080"

try:
await server.join()
finally:
await server.stop()
await server.closeWait()
# ANCHOR_END: main

when isMainModule:
waitFor main()
# ANCHOR_END: all
13 changes: 13 additions & 0 deletions docs/examples/http_server/chapter3/chapter3.nimble
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Package

version = "0.1.0"
author = "Status Research & Development GmbH"
description = "Chronos HTTP server tutorial example"
license = "Apache-2.0"
srcDir = "src"
bin = @["dashboard"]

# Dependencies

requires "nim >= 2.0.0"
requires "chronos"
92 changes: 92 additions & 0 deletions docs/examples/http_server/chapter3/src/dashboard.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# ANCHOR: all
# ANCHOR: import
import chronos/apps/http/httpserver
import std/[json, tables]
# ANCHOR_END: import

# ANCHOR: data
var reports {.threadvar.}: Table[string, string]
# ANCHOR_END: data

# ANCHOR: handler
proc handler(
reqfence: RequestFence
): Future[HttpResponseRef] {.async: (raises: [CancelledError]).} =
let request = reqfence.valueOr:
return defaultResponse()

try:
case request.uri.path
of "/":
await request.respond(Http200, "Welcome to the Status Dashboard!")

# ANCHOR: status_get
of "/status":
var output = "Current Service Status:\n"
if reports.len == 0:
output.add("- No reports available.")
else:
for name, status in reports:
output.add("- " & name & ": " & status & "\n")
await request.respond(Http200, output)
# ANCHOR_END: status_get

# ANCHOR: report_post
of "/report":
if request.meth != MethodPost:
return await request.respond(Http405, "Method Not Allowed")

let
body = await request.getBody()
data =
try:
parseJson(bytesToString(body))
except CatchableError:
return await request.respond(Http400, "Invalid JSON.")
name =
try:
data["name"].getStr()
except KeyError:
return await request.respond(Http400, "Missing 'name' field.")
status =
try:
data["status"].getStr()
except KeyError:
return await request.respond(Http400, "Missing 'status' field.")

reports[name] = status
echo "Received report: " & name & " is " & status

await request.respond(Http200, "Report received.")
# ANCHOR_END: report_post
else:
await request.respond(Http404, "Page not found.")
except HttpError as exc:
defaultResponse(exc)

# ANCHOR_END: handler

# ANCHOR: main
proc main() {.async: (raises: [TransportAddressError, CancelledError]).} =
reports = initTable[string, string]()

let
address = initTAddress("127.0.0.1:8080")
server = HttpServerRef.new(address, handler).valueOr:
echo "Unable to start HTTP server: " & error
return

server.start()
echo "HTTP server running on http://127.0.0.1:8080"

try:
await server.join()
finally:
await server.stop()
await server.closeWait()

# ANCHOR_END: main

when isMainModule:
waitFor main()
# ANCHOR_END: all
13 changes: 13 additions & 0 deletions docs/examples/http_server/chapter4/chapter4.nimble
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Package

version = "0.1.0"
author = "Status Research & Development GmbH"
description = "Chronos HTTP server tutorial example"
license = "Apache-2.0"
srcDir = "src"
bin = @["dashboard"]

# Dependencies

requires "nim >= 2.0.0"
requires "chronos"
Loading
Loading