From d2d982db625f56486b0a477ebad21bc9863fd6ae Mon Sep 17 00:00:00 2001 From: Jacob Quinn Date: Fri, 9 Oct 2026 07:32:40 -0600 Subject: [PATCH] Make content sniffing trim-safe `_SNIFF_SIGNATURES` was an `Any[...]` vector, so every `_sniff_match` and `_sniff_content_type` call in the `sniff` loop dispatched at runtime, which `juliac --trim=safe` rejects. Type the table as a three-member union and check the three trailing data-free signatures (MP4, JSON, text) from a tuple afterwards. Both loops stay within inference's union-splitting limit, so dispatch is static. Signature order is unchanged. The open-fileserver trim workload now calls `servecontent` without a content type and `HTTP.sniff` directly. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 2 ++ src/http_sniff.jl | 15 ++++++++++----- test/http_trim_open_fileserver.jl | 5 +++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4776f95d5..0a57da866 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -86,6 +86,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 until the handler finishes. ([#1384]) ### Fixed +- `HTTP.sniff`, and `servecontent` without a `content_type`, now compile under + `juliac --trim=safe`. Content sniffing no longer dispatches at runtime. - Requests with a zero-length streaming body can be copied for retries and redirects. The first send retains and closes the producer; later sends replay the empty payload without trying to clone the producer. diff --git a/src/http_sniff.jl b/src/http_sniff.jl index 5d7d05d79..61336f3a3 100644 --- a/src/http_sniff.jl +++ b/src/http_sniff.jl @@ -1,4 +1,4 @@ -# Content sniffing helpers used by multipart/form request bodies. +# Content sniffing for `sniff`, multipart/form request bodies, and `servecontent`. const _SNIFF_MAX_LENGTH = 512 const _SNIFF_WHITESPACE = Set{UInt8}([UInt8('\t'), UInt8('\n'), UInt8('\u000c'), UInt8('\r'), UInt8(' ')]) @@ -258,7 +258,10 @@ function _sniff_match(::_SniffJSONSig, data::AbstractVector{UInt8}, firstnonws:: return true end -const _SNIFF_SIGNATURES = Any[ +# Checked in order before `_SNIFF_FALLBACK_SIGNATURES`. Keep each list to at +# most four concrete types so inference union-splits the `_sniff_match` and +# `_sniff_content_type` calls into static dispatch (required by `juliac --trim`). +const _SNIFF_SIGNATURES = Union{_SniffHTMLSig,_SniffMasked,_SniffExact}[ _SniffHTMLSig(collect(codeunits("

hi

"))) + HT.header(sniffed, "Content-Type") == "text/html; charset=utf-8" || error("unexpected sniffed content type") + HT.sniff("{\"ok\":true}") == "application/json; charset=utf-8" || error("unexpected sniffed JSON content type") finally trim_shutdown_runtime() end