From cceeffe737e4cca4f705a60cbcbf8dbc9d545b48 Mon Sep 17 00:00:00 2001 From: nixo Date: Mon, 26 Oct 2020 21:06:15 +0100 Subject: [PATCH] provide functions (from Mux.jl) for live reloading --- src/Gemenon.jl | 5 +++- src/live.jl | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/server.jl | 5 ++-- src/types.jl | 7 ++++++ 4 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 src/live.jl diff --git a/src/Gemenon.jl b/src/Gemenon.jl index 81c7831..74eeb20 100644 --- a/src/Gemenon.jl +++ b/src/Gemenon.jl @@ -3,12 +3,15 @@ module Gemenon using OpenSSL using Sockets -export Connection, Request, Status, Response +export Connection, Request, Status, Response, GeminiRequest include("types.jl") include("server.jl") include("client.jl") +export @app, mux, stack, branch, page, serve +include("live.jl") + include("rw.jl") export link, document, status, not_found diff --git a/src/live.jl b/src/live.jl new file mode 100644 index 0000000..8087a76 --- /dev/null +++ b/src/live.jl @@ -0,0 +1,67 @@ +## 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], ":") + 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 diff --git a/src/server.jl b/src/server.jl index 2c5849f..9c00c4d 100644 --- a/src/server.jl +++ b/src/server.jl @@ -81,8 +81,9 @@ function handle_connection(f, server, context, io, verbose) # println("HERE") OpenSSL.do_sock_read(client) end - f(Connection(server, client), - Request(String(client.context.data))) + f(GeminiRequest(Connection(server, client), + Request(String(client.context.data)), + Dict())) break end end diff --git a/src/types.jl b/src/types.jl index 1f84f59..89fc1c0 100644 --- a/src/types.jl +++ b/src/types.jl @@ -166,3 +166,10 @@ struct Connection server::Sockets.TCPServer client::SSLClient end + +struct GeminiRequest + conn::Connection + req::Request + data::Dict{Symbol,Any} +end +