82 lines
2.5 KiB
Clojure
Executable file
82 lines
2.5 KiB
Clojure
Executable file
#!/usr/bin/env bb
|
|
#_" -*- mode: clojure; -*-"
|
|
;; Source: https://gist.github.com/holyjak/36c6284c047ffb7573e8a34399de27d8
|
|
|
|
;; Based on https://github.com/babashka/babashka/blob/master/examples/image_viewer.clj
|
|
(ns file-server
|
|
(:require [babashka.fs :as fs]
|
|
[clojure.java.browse :as browse]
|
|
[clojure.string :as str]
|
|
[clojure.tools.cli :refer [parse-opts]]
|
|
[hiccup2.core :as html]
|
|
[org.httpkit.server :as server])
|
|
(:import [java.net URLDecoder URLEncoder]))
|
|
|
|
(def cli-options [["-p" "--port PORT" "Port for HTTP server" :default 8090 :parse-fn #(Integer/parseInt %)]
|
|
["-d" "--dir DIR" "Directory to serve files from" :default "."]
|
|
["-h" "--help" "Print usage info"]])
|
|
|
|
(def parsed-args (parse-opts *command-line-args* cli-options))
|
|
(def opts (:options parsed-args))
|
|
|
|
(cond
|
|
(:help opts)
|
|
(do (println "Start a http server for static files in the given dir. Usage:\n" (:summary parsed-args))
|
|
(System/exit 0))
|
|
|
|
(:errors parsed-args)
|
|
(do (println "Invalid arguments:\n" (str/join "\n" (:errors parsed-args)))
|
|
(System/exit 1))
|
|
|
|
:else
|
|
:continue)
|
|
|
|
|
|
(def port (:port opts))
|
|
(def dir (fs/path (:dir opts)))
|
|
|
|
(assert (fs/directory? dir) (str "The given dir `" dir "` is not a directory."))
|
|
|
|
(defn index [f]
|
|
(let [files (map #(str (.relativize dir %))
|
|
(fs/list-dir f))]
|
|
{:body (-> [:html
|
|
[:head
|
|
[:meta {:charset "UTF-8"}]
|
|
[:title (str "Index of `" f "`")]]
|
|
[:body
|
|
[:h1 "Index of " [:code (str f)]]
|
|
[:ul
|
|
(for [child files]
|
|
[:li [:a {:href (URLEncoder/encode (str child))} child
|
|
(when (fs/directory? (fs/path dir child)) "/")]])]
|
|
[:hr]
|
|
[:footer {:style {"text-aling" "center"}} "Served by http-server.clj"]]]
|
|
html/html
|
|
str)}))
|
|
|
|
(defn body [path]
|
|
{:body (fs/file path)})
|
|
|
|
(server/run-server
|
|
(fn [{:keys [:uri]}]
|
|
(let [f (fs/path dir (str/replace-first (URLDecoder/decode uri) #"^/" ""))
|
|
index-file (fs/path f "index.html")]
|
|
(cond
|
|
(and (fs/directory? f) (fs/readable? index-file))
|
|
(body index-file)
|
|
|
|
(fs/directory? f)
|
|
(index f)
|
|
|
|
(fs/readable? f)
|
|
(body f)
|
|
|
|
:else
|
|
{:status 404 :body (str "Not found `" f "` in " dir)})))
|
|
{:port port})
|
|
|
|
(println "Starting http server at " port "for" (str dir))
|
|
(browse/browse-url (format "http://localhost:%s/" port))
|
|
|
|
@(promise)
|