use(require(“atomy”))
require(“webrick”) require(“puma”)
– shim in svg content-type support WEBrick HTTPUtils DefaultMimeTypes = “image/svg+xml”
class(Server):
def(initialize(@source, @destination, @processor, @renderer)): @mutex = Mutex new
def(Server serve(port)):
server = Puma Server new( [env]: relative-path = env["REQUEST_PATH"] sub(r"^\/", "") local-abs-path = File absolute-path(relative-path, @destination) if(relative-path == "favicon.ico") then: respond-to-favicon else: respond-to-path(relative-path, local-abs-path) ) server add-tcp-listener("0.0.0.0", port) -- server mount-proc("/") [req, res]: trap("INT"): server stop puts(i"serving on port #{port}") server run(false)
def(Server respond-to-favicon()):
[404, #{}, []]
def(Server respond-to-path(relative-path, local-abs-path)):
do { rebuild-if-needed if(File directory?(local-abs-path)) then: respond-to-file(File join(local-abs-path, "index.html")) else: respond-to-file(local-abs-path) } rescue: e: backtrace = Rubinius Backtrace backtrace(e locations) show("\n", false) message = i"#{e to-s}\n#{backtrace}" puts(message) respond-with-error(message)
def(Server respond-with-error(message)):
[500, #{"Content-Type" -> "text/html"}, [i"<pre>#{message}</pre>"]]
def(Server respond-to-file(local-abs-path)):
[200, #{"Content-Type" -> guess-content-type(local-abs-path)}, [File read(local-abs-path)]]
def(Server guess-content-type(path)):
extension = File extname(path) sub(r"^\.", "") WEBrick HTTPUtils DefaultMimeTypes fetch(extension): "application/octet-stream"
def(Server rebuild-if-needed):
@mutex synchronize: when(@last-disk-state == disk-state): return puts(i"rebuilding #{@source}...") -- clear out already-loaded document modules $LOADED_FEATURES reject! &.end-with?(".any") @processor process(@source, @renderer, @destination) puts("done") -- Save disk state after rebuilding, to ignore the built artifacts -- themselves @last-disk-state = disk-state
– TODO: if this is defined in the class: we get an unknown constant 'Particle' def(Server disk-state):
-- collect disk state of files surrounding input file Dir glob(File expand-path("../**/*", @source)) collect &.( File absolute-path(_) ) collect [path] { [path, File stat(path) mtime to-s] } sort