Skip to content

Commit 39c46f6

Browse files
authored
Default the :http backend to HTTP/1.1 on HTTP.jl 2.x (#100)
* Default the :http backend to HTTP/1.1 on HTTP.jl 2.x HTTP.jl 2.x defaults to prefer_http2=true and its :auto ALPN silently upgrades any capable TLS server to HTTP/2. The streaming abort model added in #98 (interrupt the read task + close the stream when the consumer closes the channel) assumes one request per connection, as in HTTP/1.1. Over a reused HTTP/2 connection each aborted watch/streaming cycle leaves per-stream state behind, and after a few cycles the shared connection read loop wedges (observed as a hung Kubernetes watch: the socket in CLOSE-WAIT with the h2 read loop parked in read_frame!). Pin the transport to HTTP/1.1 (protocol=:h1) for both the plain and streaming request paths, guarded by the existing _HTTP_V2 check (1.x has no protocol keyword). The choice is overridable per client via the :http_protocol option (:auto or :h2) for callers who want the 2.x default. * update patch version
1 parent 7bc9734 commit 39c46f6

2 files changed

Lines changed: 15 additions & 1 deletion

File tree

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ keywords = ["Swagger", "OpenAPI", "REST"]
44
license = "MIT"
55
desc = "OpenAPI server and client helper for Julia"
66
authors = ["JuliaHub Inc."]
7-
version = "0.2.4"
7+
version = "0.2.5"
88

99
[deps]
1010
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

src/client/httplibs/juliaweb_http.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@ end
7373
# `read_idle_timeout` (`readtimeout` still works but emits a deprecation warning).
7474
_http_read_timeout_kw(timeout) = _HTTP_V2 ? (; read_idle_timeout=timeout) : (; readtimeout=timeout)
7575

76+
# Transport protocol selection on HTTP.jl 2.x. 2.x defaults to `prefer_http2=true`
77+
# and transparently upgrades any ALPN-capable TLS server to HTTP/2. We default to
78+
# HTTP/1.1 (`:h1`) instead, because OpenAPI's streaming abort model — interrupt the
79+
# read task and close the stream when the consumer closes the channel — assumes one
80+
# request per connection, as in HTTP/1.1. Observed behavior over a reused HTTP/2
81+
# connection: after a few aborted watch/streaming cycles the shared connection's read
82+
# loop wedges (the k8s watch hang), most likely from per-stream state left behind by
83+
# the aborts. Callers who want the 2.x default can set `:http_protocol => :auto`
84+
# (or `:h2`) in the client options. HTTP/1.x has no `protocol` keyword, so pass none.
85+
_http_protocol_kw(ctx) =
86+
_HTTP_V2 ? (; protocol=get(ctx.client.clntoptions, :http_protocol, :h1)) : (;)
87+
7688
function get_response_property(raw::HTTP.Response, name::Symbol)
7789
if name === :message
7890
return _http_statustext(raw)
@@ -265,6 +277,7 @@ end
265277
function _http_request(ctx, method, url, headers, body, timeout, bytesread, captured_response, output)
266278
captured_response[] = http_response = HTTP.request(method, url, headers, body;
267279
_http_read_timeout_kw(timeout)...,
280+
_http_protocol_kw(ctx)...,
268281
connect_timeout=timeout ÷ 2,
269282
retry=false,
270283
redirect=true,
@@ -282,6 +295,7 @@ function _http_streaming_request(ctx, method, url, headers, body, timeout, bytes
282295

283296
# HTTP.jl 2.0's `HTTP.open` does not accept a `verbose` keyword; only pass it on 1.x.
284297
open_kwargs = merge(_http_read_timeout_kw(timeout),
298+
_http_protocol_kw(ctx),
285299
(; connect_timeout=timeout ÷ 2,
286300
retry=false,
287301
redirect=true,

0 commit comments

Comments
 (0)