Skip to content

Commit

Permalink
change ServersCollection to contain HTTP.Servers instead of tasks (#…
Browse files Browse the repository at this point in the history
…695)

* change ServersCollection to contain `HTTP.Server`s instead of tasks

* add catch in blocking server

* close the corresponding websocket upon InterruptException

* use forceclose in down() per default
  • Loading branch information
hhaensel authored Feb 19, 2024
1 parent b16f812 commit 2111401
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 19 deletions.
43 changes: 30 additions & 13 deletions src/Server.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ using HTTP, Sockets, HTTP.WebSockets
import Millboard, Distributed, Logging
import Genie
import Distributed
import HTTP.Servers: Listener, forceclose


"""
Expand All @@ -15,8 +16,8 @@ import Distributed
Represents a object containing references to Genie's web and websockets servers.
"""
Base.@kwdef mutable struct ServersCollection
webserver::Union{Task,Nothing} = nothing
websockets::Union{Task,Nothing} = nothing
webserver::Union{T,Nothing} where T <: HTTP.Server = nothing
websockets::Union{T,Nothing} where T <: HTTP.Server = nothing
end

"""
Expand Down Expand Up @@ -101,7 +102,7 @@ function up(port::Int,
if Genie.config.websockets_server !== nothing && port !== ws_port
print_server_status("Web Sockets server starting at $host:$ws_port")

new_server.websockets = @async HTTP.listen(host, ws_port; verbose = verbose, rate_limit = ratelimit, server = wsserver,
new_server.websockets = HTTP.listen!(host, ws_port; verbose = verbose, rate_limit = ratelimit, server = wsserver,
reuseaddr = reuseaddr, http_kwargs...) do http::HTTP.Stream
if HTTP.WebSockets.isupgrade(http.message)
HTTP.WebSockets.upgrade(http) do ws
Expand All @@ -112,7 +113,7 @@ function up(port::Int,
end

command = () -> begin
HTTP.listen(parse(Sockets.IPAddr, host), port; verbose = verbose, rate_limit = ratelimit, server = server,
HTTP.listen!(parse(Sockets.IPAddr, host), port; verbose = verbose, rate_limit = ratelimit, server = server,
reuseaddr = reuseaddr, http_kwargs...) do stream::HTTP.Stream
try
if Genie.config.websockets_server !== nothing && port === ws_port && HTTP.WebSockets.isupgrade(stream.message)
Expand All @@ -134,16 +135,31 @@ function up(port::Int,
server_url *= ("?" * join(["$(k)=$(v)" for (k, v) in query], "&"))
end

status = if async
if async
print_server_status("Web Server starting at $server_url")
@async command()
else
print_server_status("Web Server starting at $server_url - press Ctrl/Cmd+C to stop the server.")
end

listener = try
command()
catch
nothing
end
if !async && !isnothing(listener)
try
wait(listener)
catch
nothing
finally
close(listener)
# close the corresponding websocket server
new_server.websockets !== nothing && isopen(new_server.websockets) && close(new_server.websockets)
end
end

if status !== nothing && status.state === :runnable
new_server.webserver = status
if listener !== nothing && isopen(listener)
new_server.webserver = listener

try
open_browser && openbrowser(server_url)
Expand Down Expand Up @@ -237,18 +253,19 @@ end
Shuts down the servers optionally indicating which of the `webserver` and `websockets` servers to be stopped.
It does not remove the servers from the `SERVERS` collection. Returns the collection.
"""
function down(; webserver::Bool = true, websockets::Bool = true) :: Vector{ServersCollection}
function down(; webserver::Bool = true, websockets::Bool = true, force::Bool = true) :: Vector{ServersCollection}
for i in 1:length(SERVERS)
down(SERVERS[i]; webserver, websockets)
down(SERVERS[i]; webserver, websockets, force)
end

SERVERS
end


function down(server::ServersCollection; webserver::Bool = true, websockets::Bool = true) :: ServersCollection
webserver && (@async Base.throwto(server.webserver, InterruptException()))
isnothing(websockets) || (websockets && (@async Base.throwto(server.websockets, InterruptException())))
function down(server::ServersCollection; webserver::Bool = true, websockets::Bool = true, force::Bool = true) :: ServersCollection
close_cmd = force ? forceclose : close
webserver && !isnothing(server.webserver) && isopen(server.webserver) && close_cmd(server.webserver)
websockets && !isnothing(server.websockets) && isopen(server.websockets) && close_cmd(server.websockets)

server
end
Expand Down
12 changes: 6 additions & 6 deletions test/tests_AppServer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@
empty!(Genie.Server.SERVERS)

servers = Genie.Server.up()
@test servers.webserver.state == :runnable
@test isopen(servers.webserver)

servers = Genie.Server.down(servers)
sleep(1)
@test servers.webserver.state == :failed
@test Genie.Server.SERVERS[1].webserver.state == :failed
@test !isopen(servers.webserver)
@test !isopen(Genie.Server.SERVERS[1].webserver)

servers = Genie.Server.down!()
empty!(Genie.Server.SERVERS)

servers = Genie.Server.up(; open_browser = false)
Genie.Server.down(servers; webserver = false)
@test servers.webserver.state == :runnable
@test isopen(servers.webserver)

servers = Genie.Server.down(servers; webserver = true)
sleep(1)
@test servers.webserver.state == :failed
@test Genie.Server.SERVERS[1].webserver.state == :failed
@test !isopen(servers.webserver)
@test !isopen(Genie.Server.SERVERS[1].webserver)

servers = nothing
end;
Expand Down

0 comments on commit 2111401

Please sign in to comment.