build: bump cpp-httplib to 0.47.0 - #653
Merged
Merged
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 65fec6f8f3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
0.16.3 was dropped from conan-center-index - only 0.28.0 and 0.47.0 are left - so the pin had stopped receiving fixes entirely. The bump was blocked until conan-io/conan-center-index#30607 landed. Every version from 0.28.0 on compiles the CFHost-based asynchronous resolver behind `CPPHTTPLIB_USE_NON_BLOCKING_GETADDRINFO`, which 0.16.3 does not have at all, and the recipe linked CoreFoundation/CFNetwork only in the narrow macOS keychain-certs case - never for iOS. Since `Server::create_server_socket` goes through `detail::create_socket` -> `getaddrinfo_with_timeout`, the server-only build pulls that resolver in, so the xcframework would have failed to link on the device slice. The fixed recipe links the frameworks on every Apple OS whenever the resolver is compiled in, and the iOS binary now carries both. Measured on the http server suite, three runs each: serving a rendered view takes 5.03 s on 0.16.3 and 0.03 s on 0.47.0. The server-side read and keep-alive timeout constants are identical between the two, so this is an upstream behaviour fix rather than a tunable. `use_non_blocking_getaddrinfo` stays at its default of True: it is what gives the bind-time resolution a timeout at all, and turning it off would trade two Apple frameworks for an unbounded blocking `getaddrinfo`. The lockfile is edited on the one line rather than regenerated - a full `scripts/conan_lock` run also re-pins pugixml and drops the option-gated entries, which does not belong in a version bump. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YSePnR4Jcj5cq3H1D11xcd
cpp-httplib 0.47.0 decommissions the server when a bind fails - both `bind_to_port` and `bind_to_any_port` set `is_decommissioned`, and every later `bind_internal()` short-circuits on it - so the "try a preferred port, fall back to any port" pattern stopped working: the second `HttpServer::bind` threw `ServerBindFailed` forever. 0.16.3 has no such flag and allowed the retry, which makes this a regression the bump introduces rather than anything new in the wrapper. `Server::stop()` is what clears the flag, and with nothing listening it does nothing else, so the failing bind path calls it before throwing. Recreating the server object would have worked too but would drop the exception handler, the socket options and the mounted routes the constructor installs. `bind_can_be_retried_after_it_failed` fails with `server bind failed: 127.0.0.1:0` without the reset. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YSePnR4Jcj5cq3H1D11xcd
andiwand
force-pushed
the
build/bump-cpp-httplib
branch
from
August 2, 2026 12:56
115a030 to
9977c60
Compare
andiwand
enabled auto-merge (squash)
August 2, 2026 12:56
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Generated with Claude Code
cpp-httplib/0.16.3has been dropped from conan-center-index — only0.28.0and0.47.0are inrecipes/cpp-httplib/config.ymlnow — so the pin had stopped receiving fixes altogether.Why this needed conan-io/conan-center-index#30607 first
Every version from 0.28.0 on compiles the CFHost-based asynchronous resolver behind
CPPHTTPLIB_USE_NON_BLOCKING_GETADDRINFO. 0.16.3 does not contain that code path at all, which is the only reason the current pin links on Apple.It matters here even though odr uses the server only, because the server reaches the resolver too:
The old recipe linked
CoreFoundation/CFNetworkonly in the narrow macOSuse_macos_keychain_certscase, and never for iOS — so the xcframework's device slice would have failed to link with undefined_CFHostCreateWithName/_CFRunLoopGetCurrent. The fixed recipe links them on every Apple OS whenever the resolver is compiled in. Verified on the freshly built device slice:Measured effect: the Apple suite's teardown
HttpServerTests/testServesARenderedView(XCTest,URLSession), instrumented to time the request and the teardown separately, two runs each:stop()Serving was never slow — the ~5 s sat entirely in teardown, where
HttpServer::stop()waits forlisten()to return andlisten()waits for its workers.Scope of that claim, deliberately narrow. This is the Apple/
URLSessionpath only; it is not a general "keep-alive no longer delays teardown" result, and I checked before claiming it. On 0.47.0 the JNI suite still needs itsConnection: close: dropping it takesserveFile()from 0.030 s to 5.07 s (three runs each). So a pooled keep-alive connection can still cost the keep-alive timeout on 0.47.0, andjni/tests/.../HttpServerTest.javakeeps its workaround. What changed for the Apple path specifically I have not pinned down, so I am not asserting a mechanism.The server-side read/write and keep-alive constants are
5in both versions, so whatever changed is upstream behaviour, not a tunable we could have set.Not to be confused with the 1 ms poll loop in
stop()that waits for alisten()between our mutex and httplib'sis_running_— unrelated, bounded, and still there.On
use_non_blocking_getaddrinfoLeft at its default (
True). It is the option that gives the bind-time DNS resolution a timeout at all — turning it off swaps two always-present Apple system frameworks for an unbounded blockinggetaddrinfo, which is the wrong direction for a server that may bind to a hostname.To be explicit about one thing: this does not remove the poll loop in
HttpServer::Impl::stop(). That loop waits for alisten()that is between our mutex and httplib'sis_running_ = true, and 0.28.0's newServer::decommission()does not close that window —listen_internal()checksis_decommissionedand setsis_running_as two separate unsynchronised steps, so astop()that skippedServer::stop()on a momentarily-falseis_running()would leave the accept loop up. The loop stays, and is untouched here.Verification
apple-macos-armv8,apple-macos-x86_64,apple-ios-armv8all build and linkHttpServerTests(testServesARenderedView,testStopIsIdempotent) pass against 0.47.0bind_to_port,bind_to_any_port,set_socket_options,set_exception_handler,listen_after_bind,is_running,stop— is unchanged in 0.47.0; the one source change needed was the bind-retry reset belowconan.lockis edited on the single line rather than regenerated: a fullscripts/conan_lockrun on this machine also re-pins pugixml and drops the option-gated entries, which does not belong in a version bump.Bind retry (addressing the review comment)
cpp-httplib 0.47.0 sets
is_decommissionedon the server when a bind fails, and every laterbind_internal()short-circuits on it, so "try a preferred port, fall back to port 0" threwServerBindFailedforever. 0.16.3 has no such flag — a regression the bump introduces. The failing path now callsServer::stop(), which is what clears it and, with nothing listening, does nothing else. Recreating the server object would also work but would drop the exception handler, socket options and routes the constructor installs.HttpServer.bind_can_be_retried_after_it_failedpins it — it fails withserver bind failed: 127.0.0.1:0without the reset.