mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-07 12:24:19 +00:00
add getPort to resolve Port(0) (#17559)
* add getPort to resolve Port(0) * fixup * use getPort in examples + tests * address comments: do not re-export Port
This commit is contained in:
@@ -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`.
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user