Skip to content

Instantly share code, notes, and snippets.

@brennop
Created May 18, 2026 00:19
Show Gist options
  • Select an option

  • Save brennop/e9aad26e64ebd473b4e17b67f72da979 to your computer and use it in GitHub Desktop.

Select an option

Save brennop/e9aad26e64ebd473b4e17b67f72da979 to your computer and use it in GitHub Desktop.
static web server in fennel
(local server ((. (require :socket) :bind) :* 3000))
(local index (with-open [file (io.open :index.html)] (file:read :*a))) ; TODO: if this fails, list dir
(fn mime-type [path]
(match (string.match (or path "") ".*%.(%w+)")
:js :text/javascript
:html :text/html
:css :text/css
_ :text/plain)) ; maybe use octet-stream instead?
(fn serialize [data status path]
(table.concat [(.. "HTTP/1.1 " status)
"Connection: close"
(.. "Content-Type: " (mime-type path))
(.. "Content-Length: " (length data))
""
data] "\r\n"))
(fn handle-client [client]
(->
(match-try (client:receive)
request (request:match "GET%s/([%p%w]*)%sHTTP/1.1")
path (io.open path :rb) ; FIXME: prevent path traversal, or don't and treat it as a feature
file (file:read :*a)
data (serialize data "200 OK" path)
(catch
(_ err 2) (serialize index "200 OK" "index.html")
(_ err) (serialize err "500 Internal Server Error")
_ (serialize "" "400 Bad Request")))
(client:send)))
(while true
(with-open [client (server:accept)]
(client:settimeout 10)
(pcall handle-client client)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment