summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md2
-rw-r--r--lib/pure/asynchttpserver.nim42
-rw-r--r--testament/lib/stdtest/netutils.nim3
-rw-r--r--tests/stdlib/tasynchttpserver_transferencoding.nim3
4 files changed, 32 insertions, 18 deletions
diff --git a/changelog.md b/changelog.md
index 7452e3182..c234bf174 100644
--- a/changelog.md
+++ b/changelog.md
@@ -71,6 +71,8 @@
 - Added `asyncdispatch.activeDescriptors` that returns the number of currently
   active async event handles/file descriptors.
 
+- Added to `asynchttpserver` `getPort` and `getSocket`.
+
 - `--gc:orc` is now 10% faster than previously for common workloads. If
   you have trouble with its changed behavior, compile with `-d:nimOldOrc`.
 
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index 38be4ceac..ec464682e 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -15,20 +15,20 @@
 ## instead of allowing users to connect directly to this server.
 
 runnableExamples("-r:off"):
-  # This example will create an HTTP server on port 8080. The server will
-  # respond to all requests with a `200 OK` response code and "Hello World"
+  # This example will create an HTTP server on an automatically chosen port.
+  # It will respond to all requests with a `200 OK` response code and "Hello World"
   # as the response body.
   import std/asyncdispatch
   proc main {.async.} =
-    const port = 8080
     var server = newAsyncHttpServer()
     proc cb(req: Request) {.async.} =
       echo (req.reqMethod, req.url, req.headers)
       let headers = {"Content-type": "text/plain; charset=utf-8"}
       await req.respond(Http200, "Hello World", headers.newHttpHeaders())
 
-    echo "test this with: curl localhost:" & $port & "/"
-    server.listen(Port(port))
+    server.listen(Port(0)) # or Port(8080) to hardcode the standard HTTP port.
+    let port = server.getPort
+    echo "test this with: curl localhost:" & $port.uint16 & "/"
     while true:
       if server.shouldAcceptRequest():
         await server.acceptRequest(cb)
@@ -41,6 +41,7 @@ runnableExamples("-r:off"):
 
 import asyncnet, asyncdispatch, parseutils, uri, strutils
 import httpcore
+from nativesockets import getLocalAddr, AF_INET
 import std/private/since
 
 export httpcore except parseHeader
@@ -70,21 +71,32 @@ type
     maxBody: int ## The maximum content-length that will be read for the body.
     maxFDs: int
 
-func getSocket*(a: AsyncHttpServer): AsyncSocket {.since: (1, 5, 1).} =
-  ## Returns the `AsyncHttpServer`s internal `AsyncSocket` instance.
-  ## 
-  ## Useful for identifying what port the AsyncHttpServer is bound to, if it
-  ## was chosen automatically.
+proc getPort*(self: AsyncHttpServer): Port {.since: (1, 5, 1).} =
+  ## Returns the port `self` was bound to.
+  ##
+  ## Useful for identifying what port `self` is bound to, if it
+  ## was chosen automatically, for example via `listen(Port(0))`.
+  runnableExamples:
+    from std/nativesockets import Port
+    let server = newAsyncHttpServer()
+    server.listen(Port(0))
+    assert server.getPort.uint16 > 0
+    server.close()
+  result = getLocalAddr(self.socket.getFd, AF_INET)[1]
+
+func getSocket*(self: AsyncHttpServer): AsyncSocket {.since: (1, 5, 1).} =
+  ## Field accessor.
   runnableExamples:
-    from std/asyncdispatch import Port
     from std/asyncnet import getFd
-    from std/nativesockets import getLocalAddr, AF_INET
+    from std/nativesockets import getLocalAddr, AF_INET, Port
     let server = newAsyncHttpServer()
     server.listen(Port(0)) # Socket is not bound until this point
-    let port = getLocalAddr(server.getSocket.getFd, AF_INET)[1]
-    doAssert uint16(port) > 0
+    # note: a more direct way to get the port is `getPort`.
+    let (laddr, port) = getLocalAddr(server.getSocket.getFd, AF_INET)
+    assert uint16(port) > 0
+    assert laddr == "0.0.0.0"
     server.close()
-  a.socket
+  self.socket
 
 proc newAsyncHttpServer*(reuseAddr = true, reusePort = false,
                          maxBody = 8388608): AsyncHttpServer =
diff --git a/testament/lib/stdtest/netutils.nim b/testament/lib/stdtest/netutils.nim
index eb913a56a..5115390e0 100644
--- a/testament/lib/stdtest/netutils.nim
+++ b/testament/lib/stdtest/netutils.nim
@@ -1,6 +1,7 @@
 import std/[nativesockets, asyncdispatch, os]
 
 proc bindAvailablePort*(handle: SocketHandle, port = Port(0)): Port =
+  ## See also `asynchttpserver.getPort`.
   block:
     var name: Sockaddr_in
     name.sin_family = typeof(name.sin_family)(toInt(AF_INET))
@@ -8,5 +9,5 @@ proc bindAvailablePort*(handle: SocketHandle, port = Port(0)): Port =
     name.sin_addr.s_addr = htonl(INADDR_ANY)
     if bindAddr(handle, cast[ptr SockAddr](addr(name)),
                 sizeof(name).Socklen) < 0'i32:
-      raiseOSError(osLastError())
+      raiseOSError(osLastError(), $port)
   result = getLocalAddr(handle, AF_INET)[1]
diff --git a/tests/stdlib/tasynchttpserver_transferencoding.nim b/tests/stdlib/tasynchttpserver_transferencoding.nim
index 34f3cef11..bfa0e2f69 100644
--- a/tests/stdlib/tasynchttpserver_transferencoding.nim
+++ b/tests/stdlib/tasynchttpserver_transferencoding.nim
@@ -27,10 +27,9 @@ template genTest(input, expected) =
 
   let server = newAsyncHttpServer()
   waitFor runSleepLoop(server)
-  let port = getLocalAddr(server.getSocket.getFd, AF_INET)[1]
   let data = postBegin & input
   var socket = newSocket()
-  socket.connect("127.0.0.1", port)
+  socket.connect("127.0.0.1", server.getPort)
   socket.send(data)
   waitFor sleepAsync(10)
   socket.close()