~h3rald/nimhttpd

c9f4a388d3a4eb2629fbc83f68c76ba30f46a833 — Fabio Cevasco 1 year, 8 months ago 9c0a59a + 732f0c4
Merge pull request #14 from unquietwiki/master

Dual-stack nimhttpd
4 files changed, 39 insertions(+), 36 deletions(-)

M LICENSE
M README.md
M src/nimhttpd.nim
M src/nimhttpdpkg/config.nim
M LICENSE => LICENSE +1 -1
@@ 1,6 1,6 @@
The MIT License (MIT)

Copyright (c) 2015-2021 Fabio Cevasco
Copyright (c) 2015-2023 Fabio Cevasco

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

M README.md => README.md +3 -3
@@ 9,14 9,14 @@ _NimHTTPd_ is a minimal web server that can be used to serve static files.

## Usage

**nimhttpd** **[** **-6** **-p:**_port_ **-t:**_title_ **-a:**_address_  **-H**:_"key: val"_ **]** **[** _directory_ **]**
**nimhttpd** **[** **-p:**_port_ **-t:**_title_ **-a:**_address_ **-6:**_ipv6_ **-H**:_"key: val"_ **]** **[** _directory_ **]**

Where:

- _directory_ is the directory to serve (default: current directory).
- _port_ is the port to listen to (default: 1337). If the specified port is
  unavailable, the number will be incremented until an available port is found.
- _address_ is the address to bind to (default: 0.0.0.0).
- _address_ is the address to bind to (default: localhost; use "0.0.0.0" to accept any IPv4 address).
- _ipv6_ is the IPv6 address to bind to (default: localhost; use "::" to accept any IPv6 address).
- _title_ is the title to use when listing the contents of a directory.
- _-6_ enables IPv6 support
- _-H_  is a custom header (Specified like in curl)

M src/nimhttpd.nim => src/nimhttpd.nim +34 -31
@@ 1,11 1,11 @@
import 
  asyncdispatch,
  asynchttpserver, 
  asynchttpserver,
  mimetypes, 
  nativesockets,
  os,
  parseopt,
  strutils, 
  strutils,
  times, 
  uri
  


@@ 23,10 23,8 @@ const
  addressDefault = "localhost"
  portDefault = 1337
  
var domain = AF_INET

let usage = """ $1 v$2 - $3
  (c) 2014-2022 $4
  (c) 2014-2023 $4

  Usage:
    nimhttpd [-p:port] [directory]


@@ 37,9 35,9 @@ let usage = """ $1 v$2 - $3
  Options:
    -t, --title    The title to use in index pages (default: Index)
    -p, --port     The port to listen to (default: $5).
    -a, --address  The address to listen to (default: $6). If the specified port is
    -a, --address  The IPv4 address to listen to (default: $6). If the specified port is
                   unavailable, the number will be incremented until an available port is found.
    -6, --ipv6     Listen to IPv6 addresses.
    -6, --ipv6     The IPv6 address to listen to (default: $6).
    -H  --header   Add a custom header. Multiple headers can be added
""" % [name, version, description, author, $portDefault, $addressDefault]



@@ 55,7 53,8 @@ type
    mimes*: MimeDb
    port*: Port
    title*: string
    address*: string
    address4*: string
    address6*: string
    name*: string
    version*: string
    headers*: HttpHeaders


@@ 109,20 108,20 @@ proc sendNotImplemented(settings: NimHttpSettings, path: string): NimHttpRespons
  return (code: Http501, content: hPage(settings, content, $int(Http501), "Not Implemented"), headers: {"Content-Type": "text/html"}.newHttpHeaders())

proc sendStaticFile(settings: NimHttpSettings, path: string): NimHttpResponse =
  let mimes = settings.mimes
  var ext = path.splitFile.ext
  if ext == "":
    ext = ".txt"
  ext = ext[1 .. ^1]
  var
    mimes = settings.mimes
    ext = path.splitFile.ext
  if ext == "": ext = ".txt" else: ext = ext[1 .. ^1]
  let mimetype = mimes.getMimetype(ext.toLowerAscii)
  var file = path.readFile
  return (code: Http200, content: file, headers: {"Content-Type": mimetype}.newHttpHeaders)

proc sendDirContents(settings: NimHttpSettings, dir: string): NimHttpResponse = 
  let cwd = settings.directory.absolutePath
  var res: NimHttpResponse
  var files = newSeq[string](0)
  var path = dir.absolutePath
  var
    res: NimHttpResponse
    cwd = settings.directory.absolutePath
    files = newSeq[string](0)
    path = dir.absolutePath
  if not path.startsWith(cwd):
    path = cwd
  if path != cwd and path != cwd&"/" and path != cwd&"\\":


@@ 158,14 157,14 @@ proc handleCtrlC() {.noconv.} =
setControlCHook(handleCtrlC)

proc genMsg(settings: NimHttpSettings): string =
  let url = "http://$1:$2/" % [settings.address, $settings.port.int]
  let t = now()
  let pid = getCurrentProcessId()
  result = """$1 v$2
Address:       $3 
Directory:     $4
Current Time:  $5 
PID:           $6""" % [settings.name, settings.version, url, settings.directory.quoteShell, $t, $pid]
Address4:      $3
Address6:      $4
Directory:     $5
Current Time:  $6 
PID:           $7""" % [settings.name, settings.version, settings.address4, settings.address6, settings.directory.quoteShell, $t, $pid]

proc serve*(settings: NimHttpSettings) =
  var server = newAsyncHttpServer()


@@ 186,12 185,14 @@ proc serve*(settings: NimHttpSettings) =
      res.headers[key] = value
    await req.respond(res.code, res.content, res.headers)
  echo genMsg(settings)
  asyncCheck server.serve(settings.port, handleHttpRequest, settings.address, -1, domain)
  asyncCheck server.serve(settings.port, handleHttpRequest, settings.address4, -1, AF_INET)
  asyncCheck server.serve(settings.port, handleHttpRequest, settings.address6, -1, AF_INET6)

when isMainModule:

  var port = portDefault
  var address = addressDefault
  var address4 = addressDefault
  var address6 = addressDefault
  var logging = false
  var www = getCurrentDir()
  var title = "Index"


@@ 209,10 210,10 @@ when isMainModule:
      of "version", "v":
        echo version
        quit(0)
      of "-ipv6", "6":
        domain = AF_INET6
      of "address", "a":
        address = val
        address4 = val
      of "ipv6", "6":
        address6 = val
      of "title", "t":
        title = val
      of "port", "p":


@@ 244,9 245,10 @@ when isMainModule:
    else: 
      discard
  
  var addrInfo = getAddrInfo(address, Port(port), domain)  
  if addrInfo == nil:
    echo "Error: Could not resolve address '"&address&"'."
  var addrInfo4 = getAddrInfo(address4, Port(port), AF_INET)
  var addrInfo6 = getAddrInfo(address6, Port(port), AF_INET6)
  if (addrInfo4 == nil) and (addrInfo6 == nil):
    echo "Error: Could not resolve given IPv4 or IPv6 addresses."
    quit(1)
  
  var settings: NimHttpSettings


@@ 254,7 256,8 @@ when isMainModule:
  settings.logging = logging
  settings.mimes = newMimeTypes()
  settings.mimes.register("htm", "text/html")
  settings.address = address
  settings.address4 = address4
  settings.address6 = address6
  settings.name = name
  settings.title = title
  settings.version = version

M src/nimhttpdpkg/config.nim => src/nimhttpdpkg/config.nim +1 -1
@@ 1,5 1,5 @@
const
  pkgTitle*       = "NimHTTPd"
  pkgVersion*     = "1.4.0"
  pkgVersion*     = "1.5.0"
  pkgAuthor*      = "Fabio Cevasco & Michael Adams"
  pkgDescription* = "A tiny static file web server. IPv4 & IPv6 supported!"