JuliaWeb / HTTP.jl

HTTP for Julia
https://juliaweb.github.io/HTTP.jl/stable/
Other
643 stars 183 forks source link

Setting any readtimeout on WebSocket client causes TimeoutError #1070

Open bryaan opened 1 year ago

bryaan commented 1 year ago

Setting any readtimeout other than 0 on a websocket client causes a TimeoutError where it doesn't consider whether any messages have been received.

My understanding is it should fail when it can't read on the IO object for N seconds.

gryumov commented 1 year ago

++ data is received, but the timeout is thrown

julia> using HTTP

julia> HTTP.WebSockets.open(
           "wss://stream.binance.com:9443/stream?streams=adausdt@depth5@100ms", 
           readtimeout = 10
       ) do ws
           while true
               HTTP.WebSockets.receive(ws) |> String |> println
           end
       end
{"stream":"adausdt@depth5@100ms","data":{"lastUpdateId":7512315159,"bids":[["0.30070000","70165.90000000"],["0.30060000","82422.60000000"],["0.30050000","117418.90000000"],["0.30040000","283804.50000000"],["0.30030000","160890.30000000"]],"asks":[["0.30080000","18922.50000000"],["0.30090000","166428.60000000"],["0.30100000","179508.70000000"],["0.30110000","72360.00000000"],["0.30120000","323729.90000000"]]}}
{"stream":"adausdt@depth5@100ms","data":{"lastUpdateId":7512315161,"bids":[["0.30070000","70165.90000000"],["0.30060000","82422.60000000"],["0.30050000","117418.90000000"],["0.30040000","284112.50000000"],["0.30030000","160890.30000000"]],"asks":[["0.30080000","19077.50000000"],["0.30090000","166428.60000000"],["0.30100000","179508.70000000"],["0.30110000","72360.00000000"],["0.30120000","323729.90000000"]]}}
...
{"stream":"adausdt@depth5@100ms","data":{"lastUpdateId":7512316126,"bids":[["0.30070000","79480.40000000"],["0.30060000","89375.40000000"],["0.30050000","123721.60000000"],["0.30040000","266929.20000000"],["0.30030000","177536.10000000"]],"asks":[["0.30080000","16040.00000000"],["0.30090000","167574.90000000"],["0.30100000","228828.70000000"],["0.30110000","200246.10000000"],["0.30120000","324346.60000000"]]}}
{"stream":"adausdt@depth5@100ms","data":{"lastUpdateId":7512316144,"bids":[["0.30070000","79480.40000000"],["0.30060000","89375.40000000"],["0.30050000","123721.60000000"],["0.30040000","266929.20000000"],["0.30030000","177536.10000000"]],"asks":[["0.30080000","4840.00000000"],["0.30090000","178774.90000000"],["0.30100000","228828.70000000"],["0.30110000","200246.10000000"],["0.30120000","324346.60000000"]]}}
┌ Error: 1d995171-0d45-4293-a8ca-0bbf1b7b863d: error
│   (e, catch_backtrace()) =
│    EOFError: read end of file
│    Stacktrace:
│      [1] unsafe_read(ssl::OpenSSL.SSLStream, buf::Ptr{UInt8}, nbytes::UInt64)
│        @ OpenSSL ~/.julia/packages/OpenSSL/8wxMC/src/ssl.jl:581
│      [2] unsafe_read(c::HTTP.Connections.Connection{OpenSSL.SSLStream}, p::Ptr{UInt8}, n::UInt64)
│        @ HTTP.Connections ~/.julia/packages/HTTP/nn2yB/src/Connections.jl:200
│      [3] unsafe_read
│        @ ./io.jl:761 [inlined]
│      [4] unsafe_read(s::HTTP.Connections.Connection{OpenSSL.SSLStream}, p::Base.RefValue{UInt16}, n::Int64)
│        @ Base ./io.jl:760
│      [5] read!
│        @ ./io.jl:762 [inlined]
│      [6] read
│        @ ./io.jl:766 [inlined]
│      [7] readframe(io::HTTP.Connections.Connection{OpenSSL.SSLStream}, ::Type{HTTP.WebSockets.Frame}, buffer::Vector{UInt8}, first_fragment_opcode::HTTP.WebSockets.OpCode)
│        @ HTTP.WebSockets ~/.julia/packages/HTTP/nn2yB/src/WebSockets.jl:128
│      [8] readframe(io::HTTP.Connections.Connection{OpenSSL.SSLStream}, ::Type{HTTP.WebSockets.Frame}, buffer::Vector{UInt8})
│        @ HTTP.WebSockets ~/.julia/packages/HTTP/nn2yB/src/WebSockets.jl:127
│      [9] receive(ws::HTTP.WebSockets.WebSocket)
│        @ HTTP.WebSockets ~/.julia/packages/HTTP/nn2yB/src/WebSockets.jl:658
│     [10] (::var"#9#10")(ws::HTTP.WebSockets.WebSocket)
│        @ Main ./REPL[9]:6
│     [11] (::HTTP.WebSockets.var"#6#7"{Bool, Int64, Int64, var"#9#10", String})(http::HTTP.Streams.Stream{HTTP.Messages.Response, HTTP.Connections.Connection{OpenSSL.SSLStream}})
│        @ HTTP.WebSockets ~/.julia/packages/HTTP/nn2yB/src/WebSockets.jl:375
│     [12] macro expansion
│        @ ~/.julia/packages/HTTP/nn2yB/src/clientlayers/StreamRequest.jl:64 [inlined]
│     [13] macro expansion
│        @ ./task.jl:476 [inlined]
│     [14] streamlayer(stream::HTTP.Streams.Stream{HTTP.Messages.Response, HTTP.Connections.Connection{OpenSSL.SSLStream}}; iofunction::HTTP.WebSockets.var"#6#7"{Bool, Int64, Int64, var"#9#10", String}, decompress::Nothing, logerrors::Bool, logtag::Nothing, timedout::ConcurrentUtilities.TimedOut{HTTP.Messages.Response}, kw::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:verbose,), Tuple{Bool}}})
│        @ HTTP.StreamRequest ~/.julia/packages/HTTP/nn2yB/src/clientlayers/StreamRequest.jl:34
│     [15] streamlayer
│        @ ~/.julia/packages/HTTP/nn2yB/src/clientlayers/StreamRequest.jl:20 [inlined]
│     [16] (::HTTP.ExceptionRequest.var"#exceptions#2"{HTTP.ExceptionRequest.var"#exceptions#1#3"{typeof(HTTP.StreamRequest.streamlayer)}})(stream::HTTP.Streams.Stream{HTTP.Messages.Response, HTTP.Connections.Connection{OpenSSL.SSLStream}}; status_exception::Bool, timedout::ConcurrentUtilities.TimedOut{HTTP.Messages.Response}, logerrors::Bool, logtag::Nothing, kw::Base.Pairs{Symbol, Any, Tuple{Symbol, Symbol, Symbol}, NamedTuple{(:iofunction, :decompress, :verbose), Tuple{HTTP.WebSockets.var"#6#7"{Bool, Int64, Int64, var"#9#10", String}, Nothing, Bool}}})
│        @ HTTP.ExceptionRequest ~/.julia/packages/HTTP/nn2yB/src/clientlayers/ExceptionRequest.jl:14
│     [17] exceptions
│        @ ~/.julia/packages/HTTP/nn2yB/src/clientlayers/ExceptionRequest.jl:13 [inlined]
│     [18] #2
│        @ ~/.julia/packages/HTTP/nn2yB/src/clientlayers/TimeoutRequest.jl:21 [inlined]
│     [19] macro expansion
│        @ ~/.julia/packages/ConcurrentUtilities/9VvmK/src/try_with_timeout.jl:82 [inlined]
│     [20] (::ConcurrentUtilities.var"#2#4"{HTTP.Messages.Response, Timer, ConcurrentUtilities.TimedOut{HTTP.Messages.Response}, Channel{HTTP.Messages.Response}, HTTP.TimeoutRequest.var"#2#5"{Bool, Nothing, Base.Pairs{Symbol, Any, Tuple{Symbol, Symbol, Symbol}, NamedTuple{(:iofunction, :decompress, :verbose), Tuple{HTTP.WebSockets.var"#6#7"{Bool, Int64, Int64, var"#9#10", String}, Nothing, Bool}}}, HTTP.Streams.Stream{HTTP.Messages.Response, HTTP.Connections.Connection{OpenSSL.SSLStream}}, HTTP.ExceptionRequest.var"#exceptions#2"{HTTP.ExceptionRequest.var"#exceptions#1#3"{typeof(HTTP.StreamRequest.streamlayer)}}}})()
│        @ ConcurrentUtilities ./threadingconstructs.jl:373
└ @ HTTP.WebSockets ~/.julia/packages/HTTP/nn2yB/src/WebSockets.jl:378
ERROR: TimeoutError: Connection closed after 10 seconds