From f267adfe799f80dc7a2d00818d8e22d57f0002b6 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Mon, 6 Jan 2020 13:22:43 +0100 Subject: [PATCH] Add http server example --- README.md | 6 +++++ examples/http_server.clj | 51 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100755 examples/http_server.clj diff --git a/README.md b/README.md index e14e5bae..8570bb57 100644 --- a/README.md +++ b/README.md @@ -832,6 +832,12 @@ jet --pretty > deps.edn See [examples/pst.clj](https://github.com/borkdude/babashka/blob/master/examples/pst.clj) +### Tiny http server + +See [examples/http_server.clj](https://github.com/borkdude/babashka/blob/master/examples/http_server.clj) + +Original by [@souenzzo](https://gist.github.com/souenzzo/a959a4c5b8c0c90df76fe33bb7dfe201) + ## Thanks - [adgoji](https://www.adgoji.com/) for financial support diff --git a/examples/http_server.clj b/examples/http_server.clj new file mode 100755 index 00000000..0c045993 --- /dev/null +++ b/examples/http_server.clj @@ -0,0 +1,51 @@ +#!/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" + (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 "\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)))