Last active
September 6, 2024 15:17
-
-
Save holyjak/36c6284c047ffb7573e8a34399de27d8 to your computer and use it in GitHub Desktop.
Babashka HTTP server for serving static files, similar to `python -m http.server` but more flexible :)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bb | |
#_" -*- mode: clojure; -*-" | |
;; Based on https://github.com/babashka/babashka/blob/master/examples/image_viewer.clj | |
(ns http-server | |
(:require [babashka.fs :as fs] | |
[clojure.java.browse :as browse] | |
[clojure.string :as str] | |
[clojure.tools.cli :refer [parse-opts]] | |
[org.httpkit.server :as server] | |
[hiccup2.core :as html]) | |
(: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-align" "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) |
Babashka itself has a slightly modified version of browse-url
which does not depend on java.awt.Desktop
. Feel free to PR improvements to that function.
Haven't tried it yet... but maybe you mean text-align
on line 51 rather than text-aling
?
Thanks, @cassiel, fixed!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FYI: If you want to run this script in headless environment, the
(browse/browse-url (format "http://localhost:%s/" port))
might crash. It internally relies on/usr/bin/xdg-open
on linux, which might not be available on headless distribution. So perhaps you can wrap thebrowse-url
call into something likeThere might be some better/more idiomatic way to check presensce of
xdg-open
binary. The problematicbrowse-url
function and its dependencies can be seen here https://github.com/clojure/clojure/blob/master/src/clj/clojure/java/browse.clj