From 8bbde794edc7e9f666303d1e52e892266c6cf7e4 Mon Sep 17 00:00:00 2001 From: andrei Date: Sat, 19 Nov 2022 17:34:51 +0100 Subject: [PATCH 01/13] compatible with HTTP [1.1.0 - 1.6.0) --- Project.toml | 4 +-- src/HTTP.jl | 51 +++++++++++++++++++++++++++------ test/client_listen_test.jl | 1 + test/client_serverWS_test.jl | 3 ++ test/client_server_functions.jl | 9 ++++-- test/client_test.jl | 6 ++-- test/error_test.jl | 8 +++--- test/handshaketest_functions.jl | 3 +- test/show_test.jl | 6 ++-- 9 files changed, 66 insertions(+), 25 deletions(-) diff --git a/Project.toml b/Project.toml index 87a5969..ea6c8d0 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "WebSockets" uuid = "104b5d7c-a370-577a-8038-80a2059c5097" -version = "1.5.10" +version = "1.6.0" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" @@ -10,7 +10,7 @@ Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" Sockets = "6462fe0b-24de-5631-8697-dd941f90decc" [compat] -HTTP = "0.8, 0.9, 1" +HTTP = "1.1.0, 1.5" julia = "0.7, 1" [extras] diff --git a/src/HTTP.jl b/src/HTTP.jl index a3dc195..805bc9f 100644 --- a/src/HTTP.jl +++ b/src/HTTP.jl @@ -7,18 +7,14 @@ import HTTP:Response, # For upgrade setstatus, # For upgrade startwrite, # For upgrade startread, # For _openstream - handle, # For _servercoroutine - Connection, # For handshaketest - Transaction,# For handshaketest URI, # For open - Handler, # For WebSocketHandler, ServerWS, error_test - RequestHandlerFunction, # For ServerWS StatusError, # For open Servers, # For further imports Streams, # For further imports ConnectionPool # For further imports import HTTP.ConnectionPool: - getrawstream # For _openstream + getrawstream, # For _openstream + Connection # For handshaketest import HTTP.Streams: Stream # For is_upgrade, handshaketest import HTTP.Servers: MbedTLS # For further imports @@ -95,9 +91,9 @@ function open(f::Function, url; verbose=false, subprotocol = "", kw...) "GET", uri, headers; reuse_limit=0, verbose=verbose ? 2 : 0, kw...) catch err - if typeof(err) <: HTTP.IOExtras.IOError - throw(WebSocketClosedError(" while open ws|client: $(string(err.e.msg))")) - elseif typeof(err) <: HTTP.StatusError + if typeof(err) <: HTTP.Exceptions.ConnectError + throw(WebSocketClosedError(" while open ws|client: $(string(err.error))")) + elseif typeof(err) <: HTTP.StatusError return err.response else rethrow(err) @@ -270,6 +266,43 @@ target(req::Request) = req.target subprotocol(req::Request) = header(req, "Sec-WebSocket-Protocol") origin(req::Request) = header(req, "Origin") +#functions which are not present in HTTP 1.0 +function handle end + +abstract type Handler end + +""" + RequestHandler + +Abstract type representing objects that handle `HTTP.Request` and return `HTTP.Response` objects. + +See `?HTTP.RequestHandlerFunction` for an example of a concrete implementation. +""" +abstract type RequestHandler <: Handler end + +""" + StreamHandler + +Abstract type representing objects that handle `HTTP.Stream` objects directly. + +See `?HTTP.StreamHandlerFunction` for an example of a concrete implementation. +""" +abstract type StreamHandler <: Handler end + +""" + RequestHandlerFunction(f) + +A function-wrapper type that is a subtype of `RequestHandler`. Takes a single function as an argument +that should be of the form `f(::HTTP.Request) => HTTP.Response` +""" +struct RequestHandlerFunction{F} <: RequestHandler + func::F # func(req) +end + +#handle(h::RequestHandlerFunction, req::Request, args...) = h.func(req, args...) +handle(h::RequestHandlerFunction, stream::HTTP.Streams.Stream, args...) = h.func(stream, args...) + + """ WSHandlerFunction(f::Function) <: Handler The provided argument should be one of the forms diff --git a/test/client_listen_test.jl b/test/client_listen_test.jl index d8943e2..14d94d5 100644 --- a/test/client_listen_test.jl +++ b/test/client_listen_test.jl @@ -18,6 +18,7 @@ for i = 1:3 println("Status($(i)): $(status)") @test 200 == status close(server) + sleep(1) end end diff --git a/test/client_serverWS_test.jl b/test/client_serverWS_test.jl index 567d9e0..f62434f 100644 --- a/test/client_serverWS_test.jl +++ b/test/client_serverWS_test.jl @@ -41,6 +41,7 @@ for i = 1:3 server = startserver(url=ip) @test 200 == WebSockets.HTTP.request("GET", "http://$SURL:$PORT").status close(server) + sleep(1) end end @@ -50,6 +51,7 @@ let WebSockets.open(initiatingws, "ws://$SURL:$PORT") close(server) end +sleep(1) @info "ServerWS: Server side initiates message exchange." let @@ -57,6 +59,7 @@ let WebSockets.open(echows, "ws://$SURL:$PORT", subprotocol = SUBPROTOCOL) close(server) end +sleep(1) @info "ServerWS: Server side initiates message exchange. Close from within server side handler." let diff --git a/test/client_server_functions.jl b/test/client_server_functions.jl index 0efe4ca..8055821 100644 --- a/test/client_server_functions.jl +++ b/test/client_server_functions.jl @@ -19,7 +19,12 @@ end `test_handler` is called by WebSockets inner function `_servercoroutine` for all accepted http requests that are not upgrades. We don't check what's actually requested. """ -test_handler(req::HTTP.Request) = HTTP.Response(200, "OK") +function test_handler(stream::HTTP.Streams.Stream) + request = stream.message + request.response = HTTP.Response(200, "OK") + request.response.request = request + write(stream, request.response.body) +end """ `test_wshandler` is called by WebSockets inner function @@ -134,7 +139,7 @@ function initiatingws(ws::WebSocket; msglengths = MSGLENGTHS, closebeforeexit = end test_serverws = WebSockets.ServerWS( - HTTP.RequestHandlerFunction(test_handler), + WebSockets.RequestHandlerFunction(test_handler), WebSockets.WSHandlerFunction(test_wshandler)) function startserver(serverws=test_serverws;url=SURL, port=PORT, verbose=false) diff --git a/test/client_test.jl b/test/client_test.jl index d27df44..f89703a 100644 --- a/test/client_test.jl +++ b/test/client_test.jl @@ -43,7 +43,7 @@ catch err global caughterr = err end @test typeof(caughterr) <: WebSocketClosedError -@test caughterr.message == " while open ws|client: connect: connection refused (ECONNREFUSED)" +@test caughterr.message == " while open ws|client: Base.IOError(\"connect: connection refused (ECONNREFUSED)\", -4078)" @info "Try open with unknown scheme." sleep(1) @@ -82,7 +82,7 @@ res = WebSockets.open((_)->nothing, URL); @info "Open with a ws client handler that throws a domain error." sleep(1) -@test_throws DomainError WebSockets.open((_)->sqrt(-2), URL); +@test_throws HTTP.Exceptions.RequestError WebSockets.open((_)->sqrt(-2), URL); @info "Stop the server in morse code." sleep(1) @@ -100,7 +100,7 @@ sethd(resp, "Upgrade" => "websocket") sethd(resp, "Sec-WebSocket-Accept" => WebSockets.generate_websocket_key(key)) sethd(resp, "Connection" => "Upgrade") servsock = BufferStream() -s = HTTP.Stream(resp, HTTP.Transaction(HTTP.Connection(servsock))) +s = HTTP.Stream(resp, HTTP.Connection(servsock)) write(servsock, resp) function dummywsh(dws::WebSockets.WebSocket{BufferStream}) close(dws.socket) diff --git a/test/error_test.jl b/test/error_test.jl index a754c9f..5659987 100644 --- a/test/error_test.jl +++ b/test/error_test.jl @@ -69,8 +69,8 @@ try read(ws_client) end catch err - @test typeof(err) <: ErrorException - @test err.msg == "Attempt to read from closed WebSocket|client. First isopen(ws), or use readguarded(ws)!" + @test typeof(err) <: HTTP.Exceptions.RequestError + @test err.error == ErrorException("Attempt to read from closed WebSocket|client. First isopen(ws), or use readguarded(ws)!") end sleep(1) @@ -85,8 +85,8 @@ try end catch err show(err) - @test typeof(err) <: WebSocketClosedError - @test err.message == " while open ws|client: stream is closed or unusable" + @test typeof(err) <: HTTP.Exceptions.RequestError + @test err.error == Base.IOError("stream is closed or unusable", 0) end close(s) diff --git a/test/handshaketest_functions.jl b/test/handshaketest_functions.jl index f00877f..72709c2 100644 --- a/test/handshaketest_functions.jl +++ b/test/handshaketest_functions.jl @@ -28,8 +28,7 @@ end function handshakeresponse(request::HTTP.Request) buf = BufferStream() c = HTTP.Connection(buf) - t = HTTP.Transaction(c) - s = HTTP.Stream(request, t) + s = HTTP.Stream(request, c) WebSockets.upgrade(dummywshandler, s) close(buf) takefirstline(buf) diff --git a/test/show_test.jl b/test/show_test.jl index a94d952..7da3f82 100644 --- a/test/show_test.jl +++ b/test/show_test.jl @@ -6,7 +6,7 @@ end let kws = [], msgs =[] ds = DummyStream(IOBuffer(), 0, 0) - for s = 0:9, h in [Base.C_NULL, Ptr{UInt64}(3)] + for s = 0:9, h in [Base.C_NULL, Ptr{Cvoid}(3)] ds.handle = h ds.status = s kwarg, msg = WebSockets._uv_status_tuple(ds) @@ -50,7 +50,7 @@ rm("temptemp") output = String(take!(io)) @test output == "✓" -ds = DummyStream(IOBuffer(), 0, 0x00000001) +ds = DummyStream(IOBuffer(), 0, Ptr{Cvoid}(1)) io = IOBuffer() WebSockets._show(io, ds) # The handle type depends on operating system, skip that @@ -222,7 +222,7 @@ let chnlout, sws, sws1, sws2 io = IOBuffer() show(io, sws) output = String(take!(io)) - @test output == "WebSockets.ServerWS(handler=h(r), wshandler=w(s)).out:Channel{Any}(sz_max:2,sz_curr:2) " + @test output == "WebSockets.ServerWS(handler=h(r), wshandler=w(s)).out:Channel{Any}(2) " sws1 = WebSockets.ServerWS(h, w) sws2 = WebSockets.ServerWS(h, w) From e736307b99622abb6e26d28943c7b7b06919b643 Mon Sep 17 00:00:00 2001 From: andrei Date: Sat, 19 Nov 2022 18:31:28 +0100 Subject: [PATCH 02/13] bump julia version to 1.6 min --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index ea6c8d0..73752c4 100644 --- a/Project.toml +++ b/Project.toml @@ -11,7 +11,7 @@ Sockets = "6462fe0b-24de-5631-8697-dd941f90decc" [compat] HTTP = "1.1.0, 1.5" -julia = "0.7, 1" +julia = "1.6" [extras] Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" From 8ebc3856dc566596ce513a35a3e0378edcc7843e Mon Sep 17 00:00:00 2001 From: andrei Date: Sat, 19 Nov 2022 18:32:17 +0100 Subject: [PATCH 03/13] appveyor somehow has a bug and tests against 1.5 julia. explicitly put LTS and latest released --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 5150cd5..cffdf7a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,7 @@ environment: matrix: - - julia_version: 1.0 - - julia_version: 1 + - julia_version: 1.6.3 + - julia_version: 1.8.3 - julia_version: nightly platform: From 9e39d2ed5504a657360078284c36e6965fdbf2b3 Mon Sep 17 00:00:00 2001 From: andrei Date: Sat, 19 Nov 2022 19:04:23 +0100 Subject: [PATCH 04/13] move sleep inside let block --- test/client_serverWS_test.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/client_serverWS_test.jl b/test/client_serverWS_test.jl index f62434f..5a91dac 100644 --- a/test/client_serverWS_test.jl +++ b/test/client_serverWS_test.jl @@ -50,21 +50,23 @@ let server = startserver() WebSockets.open(initiatingws, "ws://$SURL:$PORT") close(server) + sleep(1) end -sleep(1) @info "ServerWS: Server side initiates message exchange." let server = startserver() WebSockets.open(echows, "ws://$SURL:$PORT", subprotocol = SUBPROTOCOL) close(server) + sleep(2) end -sleep(1) + @info "ServerWS: Server side initiates message exchange. Close from within server side handler." let server = startserver() WebSockets.open(echows, "ws://$SURL:$PORT", subprotocol = SUBPROTOCOL_CLOSE) close(server) + sleep(1) end nothing From ad812608d215ffe44c478cf1afcde346452e2dfd Mon Sep 17 00:00:00 2001 From: andrei Date: Sat, 19 Nov 2022 21:26:53 +0100 Subject: [PATCH 05/13] adding more sleep --- test/client_listen_test.jl | 5 ++++- test/client_serverWS_test.jl | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/test/client_listen_test.jl b/test/client_listen_test.jl index 14d94d5..e7466e8 100644 --- a/test/client_listen_test.jl +++ b/test/client_listen_test.jl @@ -18,7 +18,7 @@ for i = 1:3 println("Status($(i)): $(status)") @test 200 == status close(server) - sleep(1) + sleep(2) end end @@ -27,6 +27,7 @@ let server = startserver(url=SURL,port=PORT) WebSockets.open(initiatingws, "ws://$SURL:$PORT") close(server) + sleep(2) end @info "Listen: Server side initiates message exchange." @@ -34,6 +35,7 @@ let server = startserver(url=SURL,port=PORT) WebSockets.open(echows, "ws://$SURL:$PORT", subprotocol = SUBPROTOCOL) close(server) + sleep(2) end @info "Listen: Server side initiates message exchange. Close from within server side handler." @@ -41,5 +43,6 @@ let server = startserver(url=SURL,port=PORT) WebSockets.open(echows, "ws://$SURL:$PORT", subprotocol = SUBPROTOCOL_CLOSE) close(server) + sleep(2) end nothing diff --git a/test/client_serverWS_test.jl b/test/client_serverWS_test.jl index 5a91dac..be9a56c 100644 --- a/test/client_serverWS_test.jl +++ b/test/client_serverWS_test.jl @@ -41,7 +41,7 @@ for i = 1:3 server = startserver(url=ip) @test 200 == WebSockets.HTTP.request("GET", "http://$SURL:$PORT").status close(server) - sleep(1) + sleep(2) end end @@ -50,7 +50,7 @@ let server = startserver() WebSockets.open(initiatingws, "ws://$SURL:$PORT") close(server) - sleep(1) + sleep(2) end @info "ServerWS: Server side initiates message exchange." @@ -67,6 +67,6 @@ let server = startserver() WebSockets.open(echows, "ws://$SURL:$PORT", subprotocol = SUBPROTOCOL_CLOSE) close(server) - sleep(1) + sleep(2) end nothing From 53e1071e639db3dc9dccc0a8b6026b91d3f2fea3 Mon Sep 17 00:00:00 2001 From: andrei Date: Sun, 20 Nov 2022 18:58:45 +0100 Subject: [PATCH 06/13] explicitly wait for servertask to finish --- test/client_listen_test.jl | 20 ++++++++------------ test/client_serverWS_test.jl | 20 ++++++++------------ test/client_server_functions.jl | 10 +++++++++- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/test/client_listen_test.jl b/test/client_listen_test.jl index e7466e8..87081b8 100644 --- a/test/client_listen_test.jl +++ b/test/client_listen_test.jl @@ -13,36 +13,32 @@ @info "Listen: Open, http response, close. Repeat three times. Takes a while." for i = 1:3 let - server = startserver(url=SURL,port=PORT) + server, servertask = startserver(url=SURL,port=PORT) status = HTTP.request("GET", "http://$SURL:$PORT").status println("Status($(i)): $(status)") @test 200 == status - close(server) - sleep(2) + close(server, servertask) end end @info "Listen: Client side initiates message exchange." let - server = startserver(url=SURL,port=PORT) + server, servertask = startserver(url=SURL,port=PORT) WebSockets.open(initiatingws, "ws://$SURL:$PORT") - close(server) - sleep(2) + close(server, servertask) end @info "Listen: Server side initiates message exchange." let - server = startserver(url=SURL,port=PORT) + server, servertask = startserver(url=SURL,port=PORT) WebSockets.open(echows, "ws://$SURL:$PORT", subprotocol = SUBPROTOCOL) - close(server) - sleep(2) + close(server, servertask) end @info "Listen: Server side initiates message exchange. Close from within server side handler." let - server = startserver(url=SURL,port=PORT) + server, servertask = startserver(url=SURL,port=PORT) WebSockets.open(echows, "ws://$SURL:$PORT", subprotocol = SUBPROTOCOL_CLOSE) - close(server) - sleep(2) + close(server, servertask) end nothing diff --git a/test/client_serverWS_test.jl b/test/client_serverWS_test.jl index be9a56c..95938d3 100644 --- a/test/client_serverWS_test.jl +++ b/test/client_serverWS_test.jl @@ -38,35 +38,31 @@ end for i = 1:3 let ip = parse(IPAddr, SURL) - server = startserver(url=ip) + server, servertask = startserver(url=ip) @test 200 == WebSockets.HTTP.request("GET", "http://$SURL:$PORT").status - close(server) - sleep(2) + close(server, servertask) end end @info "ServerWS: Client side initiates message exchange." let - server = startserver() + server, servertask = startserver() WebSockets.open(initiatingws, "ws://$SURL:$PORT") - close(server) - sleep(2) + close(server, servertask) end @info "ServerWS: Server side initiates message exchange." let - server = startserver() + server, servertask = startserver() WebSockets.open(echows, "ws://$SURL:$PORT", subprotocol = SUBPROTOCOL) - close(server) - sleep(2) + close(server, servertask) end @info "ServerWS: Server side initiates message exchange. Close from within server side handler." let - server = startserver() + server, servertask = startserver() WebSockets.open(echows, "ws://$SURL:$PORT", subprotocol = SUBPROTOCOL_CLOSE) - close(server) - sleep(2) + close(server, servertask) end nothing diff --git a/test/client_server_functions.jl b/test/client_server_functions.jl index 8055821..0653163 100644 --- a/test/client_server_functions.jl +++ b/test/client_server_functions.jl @@ -149,5 +149,13 @@ function startserver(serverws=test_serverws;url=SURL, port=PORT, verbose=false) # capture errors, if any were made during the definition. @error take!(serverws.out) end - serverws + serverws, servertask end + +function Base.close(serverws::WebSockets.ServerWS, servertask::Task) + close(serverws) + @info "waiting for servertask to finish" + wait(servertask) + @info "servertask done" + return +end \ No newline at end of file From bd080c20367a2f79b9de446fefc36a6125b0953f Mon Sep 17 00:00:00 2001 From: andrei Date: Sun, 20 Nov 2022 20:00:20 +0100 Subject: [PATCH 07/13] more debug about echo function --- test/client_server_functions.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/client_server_functions.jl b/test/client_server_functions.jl index 0653163..b8703af 100644 --- a/test/client_server_functions.jl +++ b/test/client_server_functions.jl @@ -64,20 +64,26 @@ Therefore, test results will not propagate to the enclosing test scope. """ function echows(ws::WebSocket) while isopen(ws) + @debug "reading from socket" data, ok = readguarded(ws) if ok + @debug "writing to socket" if writeguarded(ws, data) @test true else break end else + @debug "failed to read" if !isopen(ws) + @debug "socket is not open" break else + @debug "yet socket is open" break end end + sleep(0.01) end end From 9a4a378cd0048d69f81ba0060db5b257a1d57cfb Mon Sep 17 00:00:00 2001 From: andrei Date: Mon, 21 Nov 2022 15:05:42 +0100 Subject: [PATCH 08/13] experiment with non blocking read to debug test fail in CI --- test/client_server_functions.jl | 51 ++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/test/client_server_functions.jl b/test/client_server_functions.jl index b8703af..caac1ae 100644 --- a/test/client_server_functions.jl +++ b/test/client_server_functions.jl @@ -48,6 +48,53 @@ function test_wshandler(req::HTTP.Request, ws::WebSocket) end end +""" +experiment with nonblocking reads +""" +function readguarded_nonblocking(ws; sleep = 2) + chnl= Channel{Tuple{Vector{UInt8}, Bool}}(1) + # Read, output put to Channel for type stability + function _readinterruptable(c::Channel{Tuple{Vector{UInt8}, Bool}}) + try + @error "preparing to readguarded..." + #sleep !=0 && sleep(sleep) + put!(chnl, readguarded(ws)) + @error "preparing to readguarded done" + catch err + @debug sprint(showerror, err) + errtyp = typeof(err) + ok = !(errtyp != InterruptException && + errtyp != Base.IOError && + errtyp != HTTP.IOExtras.IOError && + errtyp != Base.BoundsError && + errtyp != Base.EOFError && + errtyp != Base.ArgumentError) + # Output a dummy frame that is not a control frame. + put!(chnl, (Vector{UInt8}(), ok)) + end + end + # Start reading as a task. Will not return if there is nothing to read + rt = @async _readinterruptable(chnl) + bind(chnl, rt) + yield() + # Define a task for throwing interrupt exception to the (possibly blocked) read task. + # We don't start this task because it would never return + killta = @task try + sleep(30) + @error "will be killing _readinterruptable" + throwto(rt, InterruptException()) + catch + end + # We start the killing task. When it is scheduled the second time, + # we pass an InterruptException through the scheduler. + try + schedule(killta, InterruptException(), error = false) + catch + end + # We now have content on chnl, and no additional tasks. + take!(chnl) +end + """ `echows` is called by - `test_wshandler` (in which case ws will be a server side websocket) @@ -65,7 +112,9 @@ Therefore, test results will not propagate to the enclosing test scope. function echows(ws::WebSocket) while isopen(ws) @debug "reading from socket" - data, ok = readguarded(ws) + data, ok = readguarded_nonblocking(ws) + #data, ok = readguarded(ws) + isempty(data) && @error("empty data ok=$(ok)") if ok @debug "writing to socket" if writeguarded(ws, data) From fc05f3c7bbea97cb6dc77c3f4a9e9c5d95434b21 Mon Sep 17 00:00:00 2001 From: andrei Date: Mon, 21 Nov 2022 16:11:12 +0100 Subject: [PATCH 09/13] oeek cocket before blocking read --- test/client_server_functions.jl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/client_server_functions.jl b/test/client_server_functions.jl index caac1ae..97edeb3 100644 --- a/test/client_server_functions.jl +++ b/test/client_server_functions.jl @@ -109,8 +109,22 @@ The tests will be captured if the function is run on client side. If started by the server side, this is called as part of a coroutine. Therefore, test results will not propagate to the enclosing test scope. """ + function echows(ws::WebSocket) + #give a chance for server to write anything + @debug "will wait before starting echows..." + sleep(5) + @debug "starting echows now" while isopen(ws) + try + @debug "try to peek..." + peek(ws.socket, UInt8) + @debug "got data" + catch err + @debug "nothing to read on the socket yet, $(sprint(showerror, err))" + sleep(1) + continue + end @debug "reading from socket" data, ok = readguarded_nonblocking(ws) #data, ok = readguarded(ws) From b36bccdbeeb9a63524558648af23e2e244a02db6 Mon Sep 17 00:00:00 2001 From: andrei Date: Mon, 21 Nov 2022 18:34:45 +0100 Subject: [PATCH 10/13] debug around server code --- test/client_server_functions.jl | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/client_server_functions.jl b/test/client_server_functions.jl index 97edeb3..f2da803 100644 --- a/test/client_server_functions.jl +++ b/test/client_server_functions.jl @@ -128,7 +128,11 @@ function echows(ws::WebSocket) @debug "reading from socket" data, ok = readguarded_nonblocking(ws) #data, ok = readguarded(ws) - isempty(data) && @error("empty data ok=$(ok)") + if isempty(data) + @error("empty data ok=$(ok)") + else + @error "data\n$(String(data))" + end if ok @debug "writing to socket" if writeguarded(ws, data) @@ -178,9 +182,14 @@ function initiatingws(ws::WebSocket; msglengths = MSGLENGTHS, closebeforeexit = for slen in msglengths test_str = Random.randstring(slen) forcecopy_str = test_str |> collect |> copy |> join - if writeguarded(ws, test_str) + @error "server will write $(slen) bytes \"$(test_str)\"" + ok_write = writeguarded(ws, test_str) + @error "written ok = $(ok_write)" + if ok_write yield() + @error "reading on the server side..." readback, ok = readguarded(ws) + @error "reading on the server side done" if ok # if run by the server side, this test won't be captured. if String(readback) == forcecopy_str From a410ecc478172f2830e4d540340f46aa12b2d058 Mon Sep 17 00:00:00 2001 From: andrei Date: Mon, 21 Nov 2022 19:43:30 +0100 Subject: [PATCH 11/13] more logging on the date write/read --- src/WebSockets.jl | 1 + test/client_server_functions.jl | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/WebSockets.jl b/src/WebSockets.jl index 3f043e9..3be7aed 100644 --- a/src/WebSockets.jl +++ b/src/WebSockets.jl @@ -419,6 +419,7 @@ function read_frame(ws::WebSocket) end payload_len::UInt64 = b & 0b0111_1111 + @error " a = $(a) fin = $(fin) rsv1 = $(rsv1) rsv2 = $(rsv2) rsv3 = $(rsv3) opcode = $(opcode)\nb = $(b), mask = $(mask), hasmask = $(hasmask) payload_len = $(payload_len), $(length(ab))" if payload_len == 126 payload_len = ntoh(read(ws.socket, UInt16)) # 2 bytes elseif payload_len == 127 diff --git a/test/client_server_functions.jl b/test/client_server_functions.jl index f2da803..db4d0d8 100644 --- a/test/client_server_functions.jl +++ b/test/client_server_functions.jl @@ -112,8 +112,8 @@ Therefore, test results will not propagate to the enclosing test scope. function echows(ws::WebSocket) #give a chance for server to write anything - @debug "will wait before starting echows..." - sleep(5) + #@debug "will wait before starting echows..." + #sleep(5) @debug "starting echows now" while isopen(ws) try @@ -131,10 +131,10 @@ function echows(ws::WebSocket) if isempty(data) @error("empty data ok=$(ok)") else - @error "data\n$(String(data))" + @error "data\n$(String(copy(data)))" end if ok - @debug "writing to socket" + @debug "writing to socket $(length(copy(data))) bytes of \"$(copy(data))\"" if writeguarded(ws, data) @test true else @@ -189,7 +189,7 @@ function initiatingws(ws::WebSocket; msglengths = MSGLENGTHS, closebeforeexit = yield() @error "reading on the server side..." readback, ok = readguarded(ws) - @error "reading on the server side done" + @error "reading on the server side done \"$(String(copy(readback)))\" ok = $(ok)" if ok # if run by the server side, this test won't be captured. if String(readback) == forcecopy_str From 491463bb4e05c0209bbe5abdba77d1137bdf7953 Mon Sep 17 00:00:00 2001 From: andrei Date: Mon, 21 Nov 2022 20:19:54 +0100 Subject: [PATCH 12/13] remova read_frame debug code --- src/WebSockets.jl | 1 - test/client_server_functions.jl | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/WebSockets.jl b/src/WebSockets.jl index 3be7aed..3f043e9 100644 --- a/src/WebSockets.jl +++ b/src/WebSockets.jl @@ -419,7 +419,6 @@ function read_frame(ws::WebSocket) end payload_len::UInt64 = b & 0b0111_1111 - @error " a = $(a) fin = $(fin) rsv1 = $(rsv1) rsv2 = $(rsv2) rsv3 = $(rsv3) opcode = $(opcode)\nb = $(b), mask = $(mask), hasmask = $(hasmask) payload_len = $(payload_len), $(length(ab))" if payload_len == 126 payload_len = ntoh(read(ws.socket, UInt16)) # 2 bytes elseif payload_len == 127 diff --git a/test/client_server_functions.jl b/test/client_server_functions.jl index db4d0d8..c7921f6 100644 --- a/test/client_server_functions.jl +++ b/test/client_server_functions.jl @@ -134,7 +134,7 @@ function echows(ws::WebSocket) @error "data\n$(String(copy(data)))" end if ok - @debug "writing to socket $(length(copy(data))) bytes of \"$(copy(data))\"" + @debug "writing to socket $(length(copy(data))) bytes of \"$(String(copy(data)))\"" if writeguarded(ws, data) @test true else From fc555033ef4e06032c0ef0d57e4816967cdaf601 Mon Sep 17 00:00:00 2001 From: andrei Date: Fri, 25 Nov 2022 12:06:10 +0100 Subject: [PATCH 13/13] test_handler is back to original signature deals with request not stream --- src/HTTP.jl | 8 +++++++- test/client_server_functions.jl | 7 +------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/HTTP.jl b/src/HTTP.jl index 805bc9f..0f52fba 100644 --- a/src/HTTP.jl +++ b/src/HTTP.jl @@ -300,7 +300,12 @@ struct RequestHandlerFunction{F} <: RequestHandler end #handle(h::RequestHandlerFunction, req::Request, args...) = h.func(req, args...) -handle(h::RequestHandlerFunction, stream::HTTP.Streams.Stream, args...) = h.func(stream, args...) +function handle(h::RequestHandlerFunction, stream::HTTP.Streams.Stream, args...) + request = stream.message + request.response = h.func(request, args...) + request.response.request = request + write(stream, request.response.body) +end """ @@ -405,6 +410,7 @@ function serve(serverws::ServerWS, host, port, verbose) handle(serverws.handler, stream) end catch err + @error "WebSocket: _servercoroutine CRASH\n$(sprint(showerror, err))" put!(serverws.out, err) put!(serverws.out, stacktrace(catch_backtrace())) end diff --git a/test/client_server_functions.jl b/test/client_server_functions.jl index c7921f6..7aba8a7 100644 --- a/test/client_server_functions.jl +++ b/test/client_server_functions.jl @@ -19,12 +19,7 @@ end `test_handler` is called by WebSockets inner function `_servercoroutine` for all accepted http requests that are not upgrades. We don't check what's actually requested. """ -function test_handler(stream::HTTP.Streams.Stream) - request = stream.message - request.response = HTTP.Response(200, "OK") - request.response.request = request - write(stream, request.response.body) -end +test_handler(req::HTTP.Request) = HTTP.Response(200, "OK") """ `test_wshandler` is called by WebSockets inner function