This module implements a high performance asynchronous HTTP server.
This HTTP server has not been designed to be used in production, but for testing applications locally. Because of this, when deploying your application in production you should use a reverse proxy (for example nginx) instead of allowing users to connect directly to this server.
Example: cmd: -r:off
import std/asynchttpserver
# 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.} =
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())
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)
else:
# too many concurrent connections, `maxFDs` exceeded
# wait 500ms for FDs to be closed
await sleepAsync(500)
waitFor main() proc acceptRequest(server: AsyncHttpServer; callback: proc (request: Request): Future[
void] {.closure, ...gcsafe.}): owned(Future[void]) {....stackTrace: false,
raises: [Exception], tags: [RootEffect], forbids: [].}proc getPort(self: AsyncHttpServer): Port {....raises: [OSError, Exception],
tags: [], forbids: [].}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)).
Example:
from std/nativesockets import Port let server = newAsyncHttpServer() server.listen(Port(0)) assert server.getPort.uint16 > 0 server.close()Source Edit
proc respond(req: Request; code: HttpCode; content: string;
headers: HttpHeaders = nil): Future[void] {....raises: [Exception],
tags: [RootEffect], forbids: [].}Responds to the request with the specified HttpCode, headers and content.
This procedure will not close the client socket.
Example:
import std/json
proc handler(req: Request) {.async.} =
if req.url.path == "/hello-world":
let msg = %* {"message": "Hello World"}
let headers = newHttpHeaders([("Content-Type","application/json")])
await req.respond(Http200, $msg, headers)
else:
await req.respond(Http404, "Not Found") Source Edit proc serve(server: AsyncHttpServer; port: Port;
callback: proc (request: Request): Future[void] {.closure, ...gcsafe.};
address = ""; assumedDescriptorsPerRequest = -1; domain = AF_INET): owned(
Future[void]) {....stackTrace: false, raises: [Exception], tags: [
WriteIOEffect, ReadIOEffect, RootEffect, TimeEffect], forbids: [].}Starts the process of listening for incoming HTTP connections on the specified address and port.
When a request is made by a client the specified callback will be called.
If assumedDescriptorsPerRequest is 0 or greater the server cares about the process's maximum file descriptor limit. It then ensures that the process still has the resources for assumedDescriptorsPerRequest file descriptors before accepting a connection.
You should prefer to call acceptRequest instead with a custom server loop so that you're in control over the error handling and logging.
proc shouldAcceptRequest(server: AsyncHttpServer;
assumedDescriptorsPerRequest = 5): bool {.inline,
...raises: [], tags: [], forbids: [].}
© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/asynchttpserver.html