Skip to content

Commit

Permalink
Update to HTTP.jl 1.0 (#2185)
Browse files Browse the repository at this point in the history
* Update to HTTP.jl 1.0

[HTTP.jl](https://github.com/JuliaWeb/HTTP.jl) is nearing its 1.0
release! This PR is a first draft at updating Pluto to use it.

* Use Accept-Encoding: identity in test/compiletimes.jl

* use JuliaWeb/HTTP.jl#857 for testing

* Allow using IO instead of stream for tests

* soften HTTP.jl constraint for now

* update HTTP.jl to 1.0.2

* remove test install

* close serversocket
  • Loading branch information
Pangoraw authored Jul 12, 2022
1 parent 4b57727 commit 87184bb
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 200 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[compat]
Configurations = "0.15, 0.16, 0.17"
FuzzyCompletions = "0.3, 0.4, 0.5"
HTTP = "^0.9.1"
HTTP = "^1.0.2"
HypertextLiteral = "0.7, 0.8, 0.9"
MIMEs = "0.1"
MsgPack = "1.1"
Expand Down
29 changes: 21 additions & 8 deletions src/webserver/PutUpdates.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ function serialize_message_to_stream(io::IO, message::UpdateMessage)
end

function serialize_message(message::UpdateMessage)
sprint(serialize_message_to_stream, message)
io = IOBuffer()
serialize_message_to_stream(io, message)
take!(io)
end

"Send `messages` to all clients connected to the `notebook`."
Expand Down Expand Up @@ -65,18 +67,29 @@ end
# https://github.com/JuliaWeb/HTTP.jl/issues/382
const flushtoken = Token()

function send_message(stream::HTTP.WebSocket, msg)
HTTP.send(stream, serialize_message(msg))
end
function send_message(stream::IO, msg)
write(stream, serialize_message(msg))
end

function is_stream_open(stream::HTTP.WebSocket)
!HTTP.WebSockets.isclosed(stream)
end
function is_stream_open(io::IO)
isopen(io)
end

function flushclient(client::ClientSession)
take!(flushtoken)
while isready(client.pendingupdates)
next_to_send = take!(client.pendingupdates)

try
if client.stream !== nothing
if isopen(client.stream)
if client.stream isa HTTP.WebSockets.WebSocket
client.stream.frame_type = HTTP.WebSockets.WS_BINARY
end
write(client.stream, serialize_message(next_to_send))
if is_stream_open(client.stream)
send_message(client.stream, next_to_send)
else
put!(flushtoken)
return false
Expand Down Expand Up @@ -112,4 +125,4 @@ end

function flushallclients(session::ServerSession)
flushallclients(session, values(session.connected_clients))
end
end
32 changes: 16 additions & 16 deletions src/webserver/Static.jl
Original file line number Diff line number Diff line change
Expand Up @@ -158,20 +158,20 @@ function http_router_for(session::ServerSession)
# require_secret_for_access == false
# Access to all 'risky' endpoints is still restricted to requests that have the secret cookie, but visiting `/` is allowed, and it will set the cookie. From then on the security situation is identical to
# secret_for_access == true
HTTP.@register(router, "GET", "/", with_authentication(
HTTP.register!(router, "GET", "/", with_authentication(
create_serve_onefile(project_relative_path(frontend_directory(), "index.html"));
required=security.require_secret_for_access
))
HTTP.@register(router, "GET", "/edit", with_authentication(
HTTP.register!(router, "GET", "/edit", with_authentication(
create_serve_onefile(project_relative_path(frontend_directory(), "editor.html"));
required=security.require_secret_for_access ||
security.require_secret_for_open_links,
))
# the /edit page also uses with_authentication, but this is not how access to notebooks is secured: this is done by requiring the WS connection to be authenticated.
# we still use it for /edit to do the cookie stuff, and show a more helpful error, instead of the WS never connecting.

HTTP.@register(router, "GET", "/ping", r -> HTTP.Response(200, "OK!"))
HTTP.@register(router, "GET", "/possible_binder_token_please", r -> session.binder_token === nothing ? HTTP.Response(200,"") : HTTP.Response(200, session.binder_token))
HTTP.register!(router, "GET", "/ping", r -> HTTP.Response(200, "OK!"))
HTTP.register!(router, "GET", "/possible_binder_token_please", r -> session.binder_token === nothing ? HTTP.Response(200,"") : HTTP.Response(200, session.binder_token))

function try_launch_notebook_response(action::Function, path_or_url::AbstractString; title="", advice="", home_url="./", as_redirect=true, action_kwargs...)
try
Expand All @@ -192,8 +192,8 @@ function http_router_for(session::ServerSession)
) do request::HTTP.Request
notebook_response(SessionActions.new(session); as_redirect=(request.method == "GET"))
end
HTTP.@register(router, "GET", "/new", serve_newfile)
HTTP.@register(router, "POST", "/new", serve_newfile)
HTTP.register!(router, "GET", "/new", serve_newfile)
HTTP.register!(router, "POST", "/new", serve_newfile)

# This is not in Dynamic.jl because of bookmarks, how HTML works,
# real loading bars and the rest; Same for CustomLaunchEvent
Expand Down Expand Up @@ -242,8 +242,8 @@ function http_router_for(session::ServerSession)
end
end

HTTP.@register(router, "GET", "/open", serve_openfile)
HTTP.@register(router, "POST", "/open", serve_openfile)
HTTP.register!(router, "GET", "/open", serve_openfile)
HTTP.register!(router, "POST", "/open", serve_openfile)

serve_sample = with_authentication(;
required=security.require_secret_for_access ||
Expand All @@ -262,8 +262,8 @@ function http_router_for(session::ServerSession)
advice="Please <a href='https://github.com/fonsp/Pluto.jl/issues'>report this error</a>!"
)
end
HTTP.@register(router, "GET", "/sample/*", serve_sample)
HTTP.@register(router, "POST", "/sample/*", serve_sample)
HTTP.register!(router, "GET", "/sample/*", serve_sample)
HTTP.register!(router, "POST", "/sample/*", serve_sample)

notebook_from_uri(request) = let
uri = HTTP.URI(request.target)
Expand All @@ -285,7 +285,7 @@ function http_router_for(session::ServerSession)
return error_response(400, "Bad query", "Please <a href='https://github.com/fonsp/Pluto.jl/issues'>report this error</a>!", sprint(showerror, e, stacktrace(catch_backtrace())))
end
end
HTTP.@register(router, "GET", "/notebookfile", serve_notebookfile)
HTTP.register!(router, "GET", "/notebookfile", serve_notebookfile)

serve_statefile = with_authentication(;
required=security.require_secret_for_access ||
Expand All @@ -301,7 +301,7 @@ function http_router_for(session::ServerSession)
return error_response(400, "Bad query", "Please <a href='https://github.com/fonsp/Pluto.jl/issues'>report this error</a>!", sprint(showerror, e, stacktrace(catch_backtrace())))
end
end
HTTP.@register(router, "GET", "/statefile", serve_statefile)
HTTP.register!(router, "GET", "/statefile", serve_statefile)

serve_notebookexport = with_authentication(;
required=security.require_secret_for_access ||
Expand All @@ -317,7 +317,7 @@ function http_router_for(session::ServerSession)
return error_response(400, "Bad query", "Please <a href='https://github.com/fonsp/Pluto.jl/issues'>report this error</a>!", sprint(showerror, e, stacktrace(catch_backtrace())))
end
end
HTTP.@register(router, "GET", "/notebookexport", serve_notebookexport)
HTTP.register!(router, "GET", "/notebookexport", serve_notebookexport)

serve_notebookupload = with_authentication(;
required=security.require_secret_for_access ||
Expand All @@ -338,15 +338,15 @@ function http_router_for(session::ServerSession)
advice="The contents could not be read as a Pluto notebook file. When copying contents from somewhere else, make sure that you copy the entire notebook file. You can also <a href='https://github.com/fonsp/Pluto.jl/issues'>report this error</a>!"
)
end
HTTP.@register(router, "POST", "/notebookupload", serve_notebookupload)
HTTP.register!(router, "POST", "/notebookupload", serve_notebookupload)

function serve_asset(request::HTTP.Request)
uri = HTTP.URI(request.target)
filepath = project_relative_path(frontend_directory(), relpath(HTTP.unescapeuri(uri.path), "/"))
asset_response(filepath; cacheable=should_cache(filepath))
end
HTTP.@register(router, "GET", "/*", serve_asset)
HTTP.@register(router, "GET", "/favicon.ico", create_serve_onefile(project_relative_path(frontend_directory(allow_bundled=false), "img", "favicon.ico")))
HTTP.register!(router, "GET", "/**", serve_asset)
HTTP.register!(router, "GET", "/favicon.ico", create_serve_onefile(project_relative_path(frontend_directory(allow_bundled=false), "img", "favicon.ico")))

return router
end
Loading

0 comments on commit 87184bb

Please sign in to comment.