Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Close WebSockets with a status code #348

Merged
merged 3 commits into from
Nov 8, 2018
Merged

Close WebSockets with a status code #348

merged 3 commits into from
Nov 8, 2018

Conversation

christopher-dG
Copy link
Member

@samoconnor's advice on JuliaLang/MbedTLS.jl#186 (comment) worked perfectly 🙂. I also added a check for the connection still being open, since writing to a closed one throws an error.
Closes #347

@ararslan ararslan requested a review from quinnj November 7, 2018 00:21
@christopher-dG christopher-dG mentioned this pull request Nov 7, 2018
14 tasks
@christopher-dG
Copy link
Member Author

I'm actually seeing some issues now where when I close with a status code, the next read throws an error with the same code. Investigating!

julia> HTTP.WebSockets.open("wss://echo.websocket.org") do io
       close(io; statuscode=1001)
       end
ERROR: HTTP.WebSockets.WebSocketError(1001, "")
Stacktrace:
 [1] readframe(::HTTP.WebSockets.WebSocket{HTTP.ConnectionPool.Transaction{MbedTLS.SSLContext}}) at /home/degraafc/.julia/packages/HTTP/fJZFG/src/WebSockets.jl:268
 [2] #close#10(::Int64, ::Function, ::HTTP.WebSockets.WebSocket{HTTP.ConnectionPool.Transaction{MbedTLS.SSLContext}}) at /home/degraafc/.julia/packages/HTTP/fJZFG/src/WebSockets.jl:224
 [3] #close at ./none:0 [inlined]
 [4] #3 at ./REPL[15]:2 [inlined]
 [5] (::getfield(HTTP.WebSockets, Symbol("##3#4")){Bool,getfield(Main, Symbol("##3#4")),String})(::HTTP.Streams.Stream{HTTP.Messages.Response,HTTP.ConnectionPool.Transaction{MbedTLS.SSLContext}}) at /home/degraafc/.julia/packages/HTTP/fJZFG/src/WebSockets.jl:109
 [6] macro expansion at ./task.jl:266 [inlined]
 [7] #request#1(::Nothing, ::getfield(HTTP.WebSockets, Symbol("##3#4")){Bool,getfield(Main, Symbol("##3#4")),String}, ::Int64, ::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::Type{HTTP.StreamRequest.StreamLayer}, ::HTTP.ConnectionPool.Transaction{MbedTLS.SSLContext}, ::HTTP.Messages.Request, ::Nothing) at /home/degraafc/.julia/packages/HTTP/fJZFG/src/StreamRequest.jl:54
 [8] (::getfield(HTTP, Symbol("#kw##request")))(::NamedTuple{(:iofunction, :verbose),Tuple{getfield(HTTP.WebSockets, Symbol("##3#4")){Bool,getfield(Main, Symbol("##3#4")),String},Int64}}, ::typeof(HTTP.request), ::Type{HTTP.StreamRequest.StreamLayer}, ::HTTP.ConnectionPool.Transaction{MbedTLS.SSLContext}, ::HTTP.Messages.Request, ::Nothing) at ./none:0
 [9] #request#1(::Nothing, ::Type, ::Int64, ::Base.Iterators.Pairs{Symbol,Any,Tuple{Symbol,Symbol},NamedTuple{(:iofunction, :verbose),Tuple{getfield(HTTP.WebSockets, Symbol("##3#4")){Bool,getfield(Main, Symbol("##3#4")),String},Int64}}}, ::Function, ::Type{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer}}, ::HTTP.URIs.URI, ::HTTP.Messages.Request, ::Nothing) at /home/degraafc/.julia/packages/HTTP/fJZFG/src/ConnectionRequest.jl:52
 [10] (::getfield(HTTP, Symbol("#kw##request")))(::NamedTuple{(:iofunction, :reuse_limit, :verbose),Tuple{getfield(HTTP.WebSockets, Symbol("##3#4")){Bool,getfield(Main, Symbol("##3#4")),String},Int64,Int64}}, ::typeof(HTTP.request), ::Type{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer}}}, ::HTTP.URIs.URI, ::HTTP.Messages.Request, ::Nothing) at ./none:0
 [11] (::getfield(Base, Symbol("###44#45#46")){ExponentialBackOff,getfield(HTTP.RetryRequest, Symbol("##2#3")){Bool,HTTP.Messages.Request},typeof(HTTP.request)})(::Base.Iterators.Pairs{Symbol,Any,Tuple{Symbol,Symbol,Symbol},NamedTuple{(:iofunction, :reuse_limit, :verbose),Tuple{getfield(HTTP.WebSockets, Symbol("##3#4")){Bool,getfield(Main, Symbol("##3#4")),String},Int64,Int64}}}, ::Function, ::Type, ::Vararg{Any,N} where N) at ./error.jl:203
 [12] ##44#47 at ./none:0 [inlined]
 [13] #request#1 at /home/degraafc/.julia/packages/HTTP/fJZFG/src/RetryRequest.jl:44 [inlined]
 [14] (::getfield(HTTP, Symbol("#kw##request")))(::NamedTuple{(:iofunction, :reuse_limit, :verbose),Tuple{getfield(HTTP.WebSockets, Symbol("##3#4")){Bool,getfield(Main, Symbol("##3#4")),String},Int64,Int64}}, ::typeof(HTTP.request), ::Type{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer}}}}, ::HTTP.URIs.URI, ::HTTP.Messages.Request, ::Nothing) at ./none:0
 [15] #request#1(::VersionNumber, ::String, ::Nothing, ::Function, ::Base.Iterators.Pairs{Symbol,Int64,Tuple{Symbol,Symbol},NamedTuple{(:reuse_limit, :verbose),Tuple{Int64,Int64}}}, ::Function, ::Type{HTTP.MessageRequest.MessageLayer{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer}}}}}, ::String, ::HTTP.URIs.URI, ::Array{Pair{SubString{String},SubString{String}},1}, ::Nothing) at /home/degraafc/.julia/packages/HTTP/fJZFG/src/MessageRequest.jl:47
 [16] (::getfield(HTTP, Symbol("#kw##request")))(::NamedTuple{(:iofunction, :reuse_limit, :verbose),Tuple{getfield(HTTP.WebSockets, Symbol("##3#4")){Bool,getfield(Main, Symbol("##3#4")),String},Int64,Int64}}, ::typeof(HTTP.request), ::Type{HTTP.MessageRequest.MessageLayer{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer}}}}}, ::String, ::HTTP.URIs.URI, ::Array{Pair{SubString{String},SubString{String}},1}, ::Nothing) at ./none:0
 [17] #request#1(::Int64, ::Bool, ::Base.Iterators.Pairs{Symbol,Any,Tuple{Symbol,Symbol,Symbol},NamedTuple{(:iofunction, :reuse_limit, :verbose),Tuple{getfield(HTTP.WebSockets, Symbol("##3#4")){Bool,getfield(Main, Symbol("##3#4")),String},Int64,Int64}}}, ::Function, ::Type{HTTP.RedirectRequest.RedirectLayer{HTTP.MessageRequest.MessageLayer{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer}}}}}}, ::String, ::HTTP.URIs.URI, ::Array{Pair{SubString{String},SubString{String}},1}, ::Nothing) at /home/degraafc/.julia/packages/HTTP/fJZFG/src/RedirectRequest.jl:24
 [18] (::getfield(HTTP, Symbol("#kw##request")))(::NamedTuple{(:iofunction, :reuse_limit, :verbose),Tuple{getfield(HTTP.WebSockets, Symbol("##3#4")){Bool,getfield(Main, Symbol("##3#4")),String},Int64,Int64}}, ::typeof(HTTP.request), ::Type{HTTP.RedirectRequest.RedirectLayer{HTTP.MessageRequest.MessageLayer{HTTP.RetryRequest.RetryLayer{HTTP.ExceptionRequest.ExceptionLayer{HTTP.ConnectionRequest.ConnectionPoolLayer{HTTP.StreamRequest.StreamLayer}}}}}}, ::String, ::HTTP.URIs.URI, ::Array{Pair{SubString{String},SubString{String}},1}, ::Nothing) at ./none:0
 [19] #request#5(::Base.Iterators.Pairs{Symbol,Any,Tuple{Symbol,Symbol,Symbol},NamedTuple{(:iofunction, :reuse_limit, :verbose),Tuple{getfield(HTTP.WebSockets, Symbol("##3#4")){Bool,getfield(Main, Symbol("##3#4")),String},Int64,Int64}}}, ::Function, ::String, ::HTTP.URIs.URI, ::Array{Pair{SubString{String},SubString{String}},1}, ::Nothing) at /home/degraafc/.julia/packages/HTTP/fJZFG/src/HTTP.jl:299
 [20] #request at ./none:0 [inlined]
 [21] #request#6 at /home/degraafc/.julia/packages/HTTP/fJZFG/src/HTTP.jl:313 [inlined]
 [22] #request at ./none:0 [inlined]
 [23] #open#7 at /home/degraafc/.julia/packages/HTTP/fJZFG/src/HTTP.jl:338 [inlined]
 [24] #open at ./none:0 [inlined]
 [25] #open#2(::Bool, ::Bool, ::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::getfield(Main, Symbol("##3#4")), ::String) at /home/degraafc/.julia/packages/HTTP/fJZFG/src/WebSockets.jl:89
 [26] open(::Function, ::String) at /home/degraafc/.julia/packages/HTTP/fJZFG/src/WebSockets.jl:80
 [27] top-level scope at none:0

@christopher-dG
Copy link
Member Author

christopher-dG commented Nov 8, 2018

Okay so after some digging: I thought that this package was receiving a different response from the server compared to WebSockets.jl because of the thrown exception, but it turns out that they both receive the same response, but only HTTP's implementation throws an error for non-1000 status. I'll take a look at the RFC to make sure we're sending the right stuff and also check what response we should be expecting.

@christopher-dG
Copy link
Member Author

5.5.1:

If an endpoint receives a Close frame and did not previously send a Close frame, the endpoint MUST send a Close frame in response. (When sending a Close frame in response, the endpoint typically echos the status code it received.)

src/WebSockets.jl Outdated Show resolved Hide resolved
src/WebSockets.jl Outdated Show resolved Hide resolved
@samoconnor samoconnor merged commit 804bd70 into JuliaWeb:master Nov 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HTTP.WebSockets: Add status code to Base.close
4 participants