std/asynchttpserver (original) (raw)

Source Edit

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

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)) let port = server.getPort echo "test this with: curl localhost:" & $port.uint16 & "/" while true: if server.shouldAcceptRequest(): await server.acceptRequest(cb) else:

  await sleepAsync(500)

waitFor main()

Consts

nimMaxDescriptorsFallback {.intdefine.} = 16000

fallback value for when maxDescriptors is not available. This can be set on the command line during compilation via -d:nimMaxDescriptorsFallback=N Source Edit

Procs

proc acceptRequest(server: AsyncHttpServer; callback: proc (request: Request): Future[ void] {.closure, ...gcsafe.}): owned(Future[void]) {....stackTrace: false, raises: [Exception, ValueError, OSError, SslError, LibraryError, KeyError], tags: [RootEffect], forbids: [].}

Accepts a single request. Write an explicit loop around this proc so that errors can be handled properly.Source Edit

proc close(server: AsyncHttpServer) {....raises: [LibraryError, Exception, SslError], tags: [RootEffect], forbids: [].}

Terminates the async http server instance.Source Edit

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 listen(server: AsyncHttpServer; port: Port; address = ""; domain = AF_INET) {. ...raises: [OSError, ValueError], tags: [WriteIOEffect, ReadIOEffect], forbids: [].}

Listen to the given port and address.Source Edit

proc newAsyncHttpServer(reuseAddr = true; reusePort = false; maxBody = 8388608): AsyncHttpServer {. ...raises: [], tags: [], forbids: [].}

Creates a new AsyncHttpServer instance.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, OSError, ValueError, SslError, LibraryError, KeyError], tags: [RootEffect, WriteIOEffect, ReadIOEffect, 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.

Source Edit

proc shouldAcceptRequest(server: AsyncHttpServer; assumedDescriptorsPerRequest = 5): bool {.inline, ...raises: [], tags: [], forbids: [].}

Returns true if the process's current number of opened file descriptors is still within the maximum limit and so it's reasonable to accept yet another request.Source Edit

Exports

Http417, Http503, Http431, HttpTrace, contains, Http304, Http406, Http301, $, HttpMethod, Http408, is4xx, is1xx, Http411, is3xx, Http207, Http418, Http206, toString, HttpPost, clear, Http101, httpNewLine, Http505, Http413, Http423, Http409, hasKey, Http200, []=, Http414, add, Http401, Http511, Http205, ==, Http407, Http500, Http404, Http416, Http507, Http302, HttpHeaders, Http300, Http428, Http410, is2xx, Http202, Http502, headerLimit, HttpHeaderValues, Http425, contains, newHttpHeaders, $, [], Http510, newHttpHeaders, Http305, Http451, Http504, Http426, HttpConnect, ==, Http308, del, HttpPut, Http402, pairs, Http429, HttpVersion, HttpDelete, is5xx, Http421, HttpOptions, Http307, Http102, toCaseInsensitive, HttpPatch, Http201, Http203, getOrDefault, Http100, Http208, Http501, []=, len, Http506, Http400, Http403, HttpGet, Http508, Http415, HttpHead, Http412, Http103, Http405, Http303, Http204, Http424, HttpCode, Http422, Http226, []