JuliaWeb / HTTP.jl

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

WebSockets does not support concurrent sends #1196

Open attdona opened 1 day ago

attdona commented 1 day ago

First of all, thanks for the great HTTP.jl package, I really appreciate this project!

I've noticed an issue with the WebSocket implementation: when multiple async tasks send WebSocket messages, a race condition may occur, causing the frames to become corrupted.

Below a minimal working example that exposes the issue (HTTP.jl v1.10.10).

using HTTP.WebSockets

function write_message(ws, msg)
    send(ws, msg)
end

function client_twin(ws)
    for count in 1:10
        @async write_message(ws, count)
    end
end

function serve()
    server = WebSockets.listen!("127.0.0.1", 8081) do ws
        client_twin(ws)
        # just for waiting
        receive(ws)
    end

    wait(server)
end

srvtask = @async serve()

WebSockets.open("ws://127.0.0.1:8081") do ws
    try
        while true
            s = receive(ws)
            println(s)
        end
    catch e
        @error "Ws client: $e"
    end
end;

wait(srvtask)
[ Info: Listening on: 127.0.0.1:8081, thread id: 3
┌ Error: Ws client: HTTP.WebSockets.WebSocketError(HTTP.WebSockets.CloseFrameBody(1007, "Invalid UTF-8"))

I've a forked HTTP.jl with a fix: https://github.com/cardo-org/HTTP.jl/commit/d60bb5eab707422c1ad3e62ca9398dd6e0bb4ef8

Would you be open to reviewing the fix and eventually accept a pull request?

greetings, Attilio

fredrikekre commented 1 day ago

That fix looks fine to me.