diff --git a/src/TimeoutRequest.jl b/src/TimeoutRequest.jl index 84b9d5614..0651c8a9e 100644 --- a/src/TimeoutRequest.jl +++ b/src/TimeoutRequest.jl @@ -4,6 +4,14 @@ import ..Layer, ..request using ..ConnectionPool import ..@debug, ..DEBUG_LEVEL +struct ReadTimeoutError <:Exception + readtimeout::Int +end + +function Base.showerror(io::IO, e::ReadTimeoutError) + print(io, "ReadTimeoutError: Connection closed after $(e.readtimeout) seconds") +end + """ request(TimeoutLayer, ::IO, ::Request, body) -> HTTP.Response @@ -16,9 +24,11 @@ function request(::Type{TimeoutLayer{Next}}, io::IO, req, body; readtimeout::Int=0, kw...) where Next wait_for_timeout = Ref{Bool}(true) + timedout = Ref{Bool}(false) @async while wait_for_timeout[] if isreadable(io) && inactiveseconds(io) > readtimeout + timedout[] = true close(io) @debug 1 "💥 Read inactive > $(readtimeout)s: $io" break @@ -28,6 +38,11 @@ function request(::Type{TimeoutLayer{Next}}, io::IO, req, body; try return request(Next, io, req, body; kw...) + catch e + if timedout[] + throw(ReadTimeoutError(readtimeout)) + end + rethrow(e) finally wait_for_timeout[] = false end diff --git a/test/client.jl b/test/client.jl index 9627bd94a..01f7abce3 100644 --- a/test/client.jl +++ b/test/client.jl @@ -213,7 +213,10 @@ end end @testset "readtimeout" begin - @test_throws HTTP.IOError HTTP.get("http://httpbin.org/delay/5"; readtimeout=1, retry=false) + @test_throws HTTP.TimeoutRequest.ReadTimeoutError begin + HTTP.get("http://httpbin.org/delay/5"; readtimeout=1, retry=false) + end + HTTP.get("http://httpbin.org/delay/1"; readtimeout=2, retry=false) end @testset "Retry all resolved IP addresses" begin