Skip to content

Instantly share code, notes, and snippets.

@borkdude
Forked from souenzzo/http-socket-server.clj
Last active May 3, 2021 22:59
Show Gist options
  • Save borkdude/dca50a3d5a48ac6ab2ef6aa58a4e9f6b to your computer and use it in GitHub Desktop.
Save borkdude/dca50a3d5a48ac6ab2ef6aa58a4e9f6b to your computer and use it in GitHub Desktop.
tiny http server via java sockets in babashka
#!/usr/bin/env bb
(import (java.net ServerSocket))
(require '[clojure.string :as string] '[clojure.java.io :as io])
(with-open [server-socket (new ServerSocket 8080)
client-socket (.accept server-socket)]
(loop []
(let [out (io/writer (.getOutputStream client-socket))
in (io/reader (.getInputStream client-socket))
[req-line & headers] (loop [headers []]
(let [line (.readLine in)]
(if (string/blank? line)
headers
(recur (conj headers line)))))
[_ _ path _] (re-find #"([^\s]+)\s([^\s]+)\s([^\s]+)" req-line)
f (io/file (format "./%s" path))
status (if (.exists f)
200
404)
html (fn html-fn [tag & body]
(let [attrs? (map? (first body))
attrs-str (str (when attrs?
(format " %s" (string/join " " (for [[k v] (first body)]
(format "%s=%s" (name k) (name v)))))))]
(format "<%s%s>%s</%s>"
(name tag)
attrs-str
(string/join (if attrs? (rest body) body))
(name tag))))
body (cond
(not (.exists f)) ""
(.isFile f) (slurp f)
(.isDirectory f) (format "<!DOCTYPE html>\n%s"
(html :html
(html :head
(html :title path))
(html :body
(html :h1 path)
(html :tt
(apply html :pre
(for [i (.list f)]
(html :div (html :a {:href (format "\"%s\"" i)} i)))))))))]
(prn path)
(.write out (format "HTTP/1.1 %s OK\r\nContent-Length: %s\r\n\r\n%s"
status
(count body)
body))
(.flush out))
(recur)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment