diff --git a/test/http_server_http1_tests.jl b/test/http_server_http1_tests.jl index b1d90778f..3714792e2 100644 --- a/test/http_server_http1_tests.jl +++ b/test/http_server_http1_tests.jl @@ -977,7 +977,18 @@ end response = HT._read_response(HT._ConnReader(sock), request) @test response.status == 200 @test String(_read_all_server_bytes(response.body)) == "ok" - @test isempty(read(sock)) + # The timeout response is best-effort. Depending on whether its write + # wins the race with transport shutdown, the peer observes either a + # clean EOF or a complete 408 response followed by EOF. + trailing = read(sock) + if !isempty(trailing) + timeout_io = IOBuffer(trailing) + timeout_response = HT._read_response(timeout_io) + @test timeout_response.status == 408 + @test timeout_response.close + @test timeout_response.content_length == 0 + @test eof(timeout_io) + end finally HT.@try_ignore begin NC.close(sock) diff --git a/test/http_websocket_server_tests.jl b/test/http_websocket_server_tests.jl index 7f2ac4f2d..9472d9084 100644 --- a/test/http_websocket_server_tests.jl +++ b/test/http_websocket_server_tests.jl @@ -317,45 +317,54 @@ end end @testset "HTTP.WebSockets server close notifies active sessions" begin - started = Channel{Nothing}(1) - finished = Channel{Nothing}(1) - release_handler = Channel{Nothing}(1) - server = W.listen!("127.0.0.1", 0) do ws - put!(started, nothing) + for secure in (false, true) + started = Channel{Nothing}(1) + finished = Channel{Nothing}(1) + release_handler = Channel{Nothing}(1) + tls_config = secure ? + TL.Config(verify_peer = false, cert_file = _TLS_CERT_PATH, key_file = _TLS_KEY_PATH) : + nothing + server = W.listen!("127.0.0.1", 0; tls_config = tls_config) do ws + put!(started, nothing) + try + while true + W.receive(ws) + end + catch + finally + put!(finished, nothing) + take!(release_handler) + end + end + ws = nothing + forceclose_task = nothing try - while true - W.receive(ws) + address = W.server_addr(server) + scheme = secure ? "wss" : "ws" + ws = W.open( + "$scheme://$address/shutdown"; + require_ssl_verification = false, + ) + take!(started) + forceclose_task = errormonitor(Threads.@spawn W.forceclose(server)) + take!(finished) + fetch(forceclose_task::Task) + put!(release_handler, nothing) + wait(server) + err = try + W.receive(ws::W.WebSocket) + nothing + catch err + err end - catch + @test err isa W.WebSocketError + @test (err::W.WebSocketError).message.code == 1001 finally - put!(finished, nothing) - take!(release_handler) + isready(release_handler) || HTTP.@try_ignore put!(release_handler, nothing) + forceclose_task === nothing || HTTP.@try_ignore fetch(forceclose_task::Task) + ws === nothing || HTTP.@try_ignore close(ws::W.WebSocket) + HTTP.@try_ignore W.forceclose(server) + HTTP.@try_ignore wait(server) end end - ws = nothing - forceclose_task = nothing - try - address = W.server_addr(server) - ws = W.open("ws://$address/shutdown") - take!(started) - forceclose_task = errormonitor(Threads.@spawn W.forceclose(server)) - take!(finished) - fetch(forceclose_task::Task) - put!(release_handler, nothing) - wait(server) - err = try - W.receive(ws::W.WebSocket) - nothing - catch err - err - end - @test err isa W.WebSocketError - @test (err::W.WebSocketError).message.code == 1001 - finally - isready(release_handler) || HTTP.@try_ignore put!(release_handler, nothing) - forceclose_task === nothing || HTTP.@try_ignore fetch(forceclose_task::Task) - ws === nothing || HTTP.@try_ignore close(ws::W.WebSocket) - HTTP.@try_ignore W.forceclose(server) - HTTP.@try_ignore wait(server) - end end