Skip to content

Commit f4cb20f

Browse files
quinnjclaude
andauthored
fix(server): rebuild server requests through the positional constructor (#1349)
The internal request rebuilds in _stream_request_metadata and _buffer_server_request went through the public keyword constructor. On current Julia master (1.14-dev) that Core.kwcall is no longer statically resolvable, so these two sites fail juliac --trim=safe verification (they verified on earlier 1.14-dev revisions; likely an upstream inference or verifier behavior change, worth tracking separately). Rebuilding through the positional _request_nocopy constructor sidesteps the kwcall entirely, reproduces the keyword constructor's header/trailer copy semantics explicitly, and gives _buffer_server_request one concrete-body construction per branch instead of a Union-typed rebuild. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent f2b1265 commit f4cb20f

1 file changed

Lines changed: 43 additions & 25 deletions

File tree

src/http_server.jl

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -216,19 +216,23 @@ mutable struct Stream{ISCLIENT,Req<:Request} <: IO
216216
written_bytes::Int64
217217
end
218218

219+
# Rebuild through the positional internal constructor rather than the public
220+
# keyword form: a `Core.kwcall` in this path is not statically resolvable
221+
# under `juliac --trim` on current Julia master, and the keyword
222+
# constructor's copy semantics are reproduced explicitly here.
219223
function _stream_request_metadata(request::Request)::Request{EmptyBody}
220-
return Request(
224+
return _request_nocopy(
221225
request.method,
222-
request.target;
223-
headers=request.headers,
224-
trailers=request.trailers,
225-
body=EmptyBody(),
226-
host=request.host,
227-
content_length=request.content_length,
228-
proto_major=Int(request.proto_major),
229-
proto_minor=Int(request.proto_minor),
230-
close=request.close,
231-
context=get_request_context(request),
226+
request.target,
227+
copy(request.headers),
228+
copy(request.trailers),
229+
EmptyBody(),
230+
request.host,
231+
Int64(request.content_length),
232+
UInt8(request.proto_major),
233+
UInt8(request.proto_minor),
234+
request.close,
235+
get_request_context(request),
232236
)
233237
end
234238

@@ -869,6 +873,26 @@ function _read_all_server_request_body(body::AbstractBody, max_body_bytes::Integ
869873
return take!(out)
870874
end
871875

876+
function _rebuffered_request(
877+
request::Request,
878+
body::B,
879+
content_length::Int64,
880+
)::Request{B} where {B<:AbstractBody}
881+
return _request_nocopy(
882+
request.method,
883+
request.target,
884+
copy(request.headers),
885+
copy(request.trailers),
886+
body,
887+
request.host,
888+
content_length,
889+
UInt8(request.proto_major),
890+
UInt8(request.proto_minor),
891+
request.close,
892+
get_request_context(request),
893+
)
894+
end
895+
872896
function _buffer_server_request(request::Request, max_body_bytes::Integer; close_body_on_error::Bool=true)::Request
873897
body = request.body
874898
body isa EmptyBody && return request
@@ -884,20 +908,14 @@ function _buffer_server_request(request::Request, max_body_bytes::Integer; close
884908
rethrow()
885909
end
886910
@try_ignore body_close!(body)
887-
buffered_body = isempty(body_bytes) ? EmptyBody() : BytesBody(body_bytes)
888-
return Request(
889-
request.method,
890-
request.target;
891-
headers=request.headers,
892-
trailers=request.trailers,
893-
body=buffered_body,
894-
host=request.host,
895-
content_length=length(body_bytes),
896-
proto_major=Int(request.proto_major),
897-
proto_minor=Int(request.proto_minor),
898-
close=request.close,
899-
context=get_request_context(request),
900-
)
911+
# Positional internal constructor, one call per concrete body type: the
912+
# keyword form's `Core.kwcall` is not statically resolvable under
913+
# `juliac --trim` on current Julia master, and a Union-typed body would
914+
# widen the rebuilt request. Copy semantics of the keyword constructor
915+
# are reproduced explicitly.
916+
return isempty(body_bytes) ?
917+
_rebuffered_request(request, EmptyBody(), Int64(0)) :
918+
_rebuffered_request(request, BytesBody(body_bytes), Int64(length(body_bytes)))
901919
end
902920

903921
@inline function _request_body_fully_consumed(request::Request)::Bool

0 commit comments

Comments
 (0)