## Adapted from https://github.com/JuliaWeb/Mux.jl import Base.Meta.isexpr # Live-reloading utilities for maximum server uptime mutable struct App warez end mux(f) = f mux(m, f) = x -> m(f, x) mux(ms...) = foldr(mux, ms) stack(m) = m stack(m, n) = (f, x) -> m(mux(n, f), x) stack(ms...) = foldl(stack, ms) branch(p, t) = (f, x) -> (p(x) ? t : f)(x) branch(p, t...) = branch(p, mux(t...)) function matchpath(target, path) # @show target, path params = Dict() for i = 1:length(target) # @show target[i], path[i] if startswith(target[i], ":") && !isempty(path[i]) params[Symbol(target[i][2:end])] = path[i] else target[i] == path[i] || return end end return params end function matchpath!(target, req) ps = matchpath(target, req.req.path) ps == nothing && return false # merge!(params!(req), ps) merge!(req.data, ps) # splice!(req[:path], 1:length(target)) return true end page(p::Vector, app...) = branch(req -> length(p) == length(something(req.req.path, [])) && matchpath!(p, req), app...) # page(p::AbstractString, app...) = page(splitpath(p), app...) page(app...) = page([], app...) page(app::Function, p) = page(p, app) macro app(def) @assert isexpr(def, :(=)) name, warez = def.args warez = isexpr(warez, :tuple) ? Expr(:call, :mux, map(esc, warez.args)...) : esc(warez) quote if $(Expr(:isdefined, esc(name))) $(esc(name)).warez = $warez else $(esc(name)) = App($warez) end nothing end end function serve(h::App, context, host = ip"127.0.0.1", port = 1965; kws...) @async listen((req) -> h.warez(req), context, host, port; kws...) end