2020-01-06 12:22:43 +00:00
|
|
|
#!/usr/bin/env bb
|
|
|
|
|
|
2021-03-09 09:58:27 +00:00
|
|
|
;; This example creates a file serving web server from scratch.
|
2020-05-08 21:04:21 +00:00
|
|
|
;; It accepts a single connection from a browser and serves content to the connected browser
|
|
|
|
|
;; after the connection times out, this script will serve no more.
|
2020-09-23 12:32:11 +00:00
|
|
|
;; Also see notes.clj for another web app example.
|
2020-05-08 21:04:21 +00:00
|
|
|
|
2021-03-09 09:58:27 +00:00
|
|
|
;; Note that babashka comes with org.httpkit.server now, so you don't need to
|
|
|
|
|
;; build an http server from scratch anymore. We leave this script here for educational purposes.
|
|
|
|
|
|
2020-01-06 12:22:43 +00:00
|
|
|
(import (java.net ServerSocket))
|
2020-09-23 12:32:11 +00:00
|
|
|
(require '[clojure.java.io :as io]
|
|
|
|
|
'[clojure.string :as string])
|
2020-01-06 12:22:43 +00:00
|
|
|
|
|
|
|
|
(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))
|
2020-09-23 12:32:11 +00:00
|
|
|
[req-line & _headers] (loop [headers []]
|
|
|
|
|
(let [line (.readLine in)]
|
|
|
|
|
(if (string/blank? line)
|
|
|
|
|
headers
|
|
|
|
|
(recur (conj headers line)))))
|
2020-01-06 12:22:43 +00:00
|
|
|
[_ _ 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
|
2020-06-22 18:11:25 +00:00
|
|
|
(not (.exists f)) (str path " not exist")
|
2020-01-06 12:22:43 +00:00
|
|
|
(.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)]
|
2020-06-22 18:11:25 +00:00
|
|
|
(html :div
|
2020-09-23 12:32:11 +00:00
|
|
|
(html
|
|
|
|
|
:a
|
|
|
|
|
{:href
|
|
|
|
|
(str (when (> (count path) 1) path) "/" i)} i)))))))))]
|
2020-01-06 12:22:43 +00:00
|
|
|
(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)))
|