Repository navigation
Comparing changes
Open a pull request
base repository: speak-agent/tinyhttps
base: master
head repository: mcpplibs/tinyhttps
compare: master
- 17 commits
- 25 files changed
- 4 contributors
Commits on Sep 29, 2026
-
0.3.2 --- download_to_file reports the writes the disk refused (mcppl…
…ibs#19) * fix(http): download_to_file reports the writes the disk refused download_to_file called ofs.write for each body chunk without looking at the stream, added each chunk's size to bytesWritten from what the network delivered, and set bytesWritten after ofs.close() without looking at that either. On a full disk (ENOSPC) the transfer therefore succeeded: a 420,831,054 byte download left 220,979,200 bytes on disk while bytesWritten said 420,831,054 and ok() was true, and the caller blamed the source (a checksum mismatch) for what was the local disk. Each chunk is now flushed and the stream checked. On the first failure the transfer stops reading, error becomes "write <path>: <reason>" with the reason taken from errno, and the connection is dropped instead of returned to the pool with the rest of the body still on it. Closing the file is checked the same way. Additive: DownloadToFileResult::writeFailed says the fault is the destination and not the source (a failed write, a failed close, or a file that could not be opened), and bytesReceived carries the network count. bytesWritten now counts bytes the file accepted; the two are equal for every transfer that did not fail to write. Tests: a download into /dev/full (Linux) against the in-process TLS server asserts not ok, writeFailed, bytesWritten == 0, the ENOSPC text, that reading stopped after the first refused chunk, and that the next request opens a new connection. Verified by mutation: with the stream checks removed it reports ok() and bytesWritten == 65536. * 0.3.2 --- download_to_file reports the writes the disk refused Version, CHANGELOG entry, and the README install lines name this release. * ci: bump mcpp to 2026.9.28.3 to satisfy the index floor The index now requires mcpp >= 2026.9.18.3, and MCPP_VERSION pinned 2026.8.29.1, so every `mcpp` invocation that needed the index ended at error: index requires mcpp >= 2026.9.18.3 but this is mcpp 2026.8.29.1 [E0006] That is the failure the "Smoke-test the project templates" step has reported on master since the scheduled run of 2026-09-21. MCPP_VERSION is the only place the version is named; both jobs' install steps and both cache keys read it. --------- Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for f26a77f - Browse repository at this point
Copy the full SHA f26a77fView commit details
Commits on Oct 1, 2026
-
fix(tls): refuse a server certificate that does not verify
With verifySsl = true the TLS config used MBEDTLS_SSL_VERIFY_OPTIONAL, which lets the handshake finish whatever the certificate looks like, and nothing read mbedtls_ssl_get_verify_result afterwards. A self-signed certificate, one for another host and an expired one were all accepted. Use MBEDTLS_SSL_VERIFY_REQUIRED. A failed handshake now says why in the response's statusText: the text from mbedtls_x509_crt_verify_info for a verification failure, the mbedTLS error text for any other handshake error. A refused TCP connection still reads "Connection failed". When no CA bundle can be found and verifySsl is true, the connection now fails with a message that points at SSL_CERT_FILE, instead of going ahead without verification. Tests serve self-signed, expired and wrong-name certificates from the existing in-process server and trust them through SSL_CERT_FILE, so they need no network. On Windows, where there is no bundle file, load_ca_certs reads the roots in the system ROOT certificate store that are usable for TLS servers (serverAuth) when SSL_CERT_FILE is not set. That part is built only where platform::uses_winsock is true, and has not been run on Windows.
Configuration menu - View commit details
-
Copy full SHA for 1d14c23 - Browse repository at this point
Copy the full SHA 1d14c23View commit details -
feat(proxy): authenticate to HTTP proxies and report why a tunnel was…
… refused parse_proxy_url split the URL at the first colon, so http://user:pass@proxy:3128 came out as host "user" and a port made of the digits that followed. The scheme was dropped as well, which meant an https:// proxy URL was spoken to as plain HTTP. And whatever the proxy answered to CONNECT, the caller saw "Connection failed". The URL is now parsed as scheme, userinfo, host and port. Credentials are percent-decoded and sent as a Basic Proxy-Authorization header. IPv6 hosts in brackets work, and a port outside 1..65535 is 0 instead of a truncation. ProxyConfig gains scheme, hasCredentials, user and password; host and port keep their meaning. A refused tunnel is reported in statusText: a 407 says whether credentials were sent and rejected or were needed and missing, and any other non-2xx carries the proxy's status line. Any 2xx opens the tunnel, where only 200 did. A scheme other than http is an error and is no longer read as HTTP. proxy_tunnel returns the tunnel together with the reason it could not be made. proxy_connect keeps its signature and calls it. Tests run the client against an in-process proxy and the existing TLS test server, and check both the result and what the proxy was sent.
Configuration menu - View commit details
-
Copy full SHA for 08d8540 - Browse repository at this point
Copy the full SHA 08d8540View commit details -
feat(proxy): reach an https:// proxy over TLS
A proxy URL with the https scheme was spoken to as plain HTTP, which cannot work: such a proxy expects a TLS handshake before the CONNECT. TlsSocket can now run over another TlsSocket. For an https:// proxy the client opens TLS to the proxy, sends the CONNECT inside that session, and then runs the handshake with the target inside the tunnel. The BIO of the upper session is the lower one, and wait_readable asks it rather than the descriptor, since the bytes may be decrypted there while the socket has nothing. The lower session is closed after the upper one, so its close_notify goes out before the descriptor is closed. The proxy connection is set up like the one to the target, verifySsl included. The default port for an https proxy is 443. Credentials in the URL travel inside the proxy session. Tests put the existing TLS test server in front of the target as the proxy, which needs a relay in it, and cover a body larger than a record, keep-alive through the tunnel, SSE, a response that is already decrypted in the proxy session when the client goes to wait for it, and a scheme that does not match the proxy.
Configuration menu - View commit details
-
Copy full SHA for edff1ed - Browse repository at this point
Copy the full SHA edff1edView commit details -
feat(proxy): connect through SOCKS5 proxies
socks5:// and socks5h:// proxy URLs are now understood. Both speak RFC 1928: the client offers "no authentication", and the username/password method of RFC 1929 as well when the URL carries credentials, then sends a CONNECT request and reads the reply, including the bound address that precedes the tunnel, whatever its type. The difference between the two schemes is who resolves the target's name. With socks5 the name is resolved here and the proxy is given an address; with socks5h the proxy is given the name. An address literal is sent as an address in both, and a name too long for the request is refused before anything is sent. Socket gains resolve_address for the first case, with the same manual-DNS fallback connect uses. A failure is reported in statusText as it is for an HTTP proxy: the credentials rejected, credentials needed and missing, or the proxy's reply code in words. SOCKS4 is not implemented and is an error, like any other unknown scheme. Tests script a SOCKS5 proxy byte for byte and check what it was sent for each scheme and for each authentication outcome.
Configuration menu - View commit details
-
Copy full SHA for 0733e5d - Browse repository at this point
Copy the full SHA 0733e5dView commit details -
ci, examples: a refused certificate is a failure, and the Windows sto…
…re is built and run Three additions on top of the contributor's fix, each a consequence of it. `examples/openkal` read every status 0 as "no network" and exited 0. With verification now enforced, a CA bundle the openkal stack cannot find would have passed there as a skipped run. A statusText that names a refused certificate, a missing or unparsable bundle, or a failed handshake now exits 1. The README states the two differences a build above openkal has: on Windows the socket interface is POSIX, so the ROOT store is not read and SSL_CERT_FILE is required; and connectTimeoutMs does not bound the TCP connect, because kal_net_connect has no deferred form. The Windows ROOT store reader is compiled on no platform CI covered. A windows-2022 job (msvc and llvm) builds the library and runs test_ca_store, which asserts that the store is found with nothing configured and that a public chain verifies against it. An unreachable host is a skip; a refusal is a failure. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for e52d78d - Browse repository at this point
Copy the full SHA e52d78dView commit details -
tls: link bcrypt where link.exe would not read the dependency's request
The msvc row of the new Windows job stopped at the link: entropy_poll.obj : error LNK2019: unresolved external symbol BCryptGenRandom referenced in function mbedtls_platform_entropy_poll mbedTLS's package names the library as `-lbcrypt`, which clang reads and link.exe ignores. The llvm row, the same sources under the same ABI, linked and verified a public chain against the ROOT store. The request is now also made with `#pragma comment(lib, ...)`, as socket.cppm makes it for ws2_32 and ca_bundle.cppm for crypt32. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>Configuration menu - View commit details
-
Copy full SHA for ea4dd96 - Browse repository at this point
Copy the full SHA ea4dd96View commit details -
Merge mcpplibs#21: refuse a server certificate that does not verify
verifySsl = true verifies the server certificate (fixes mcpplibs#20). Contributor commit by Cloud_Yun; maintainer commits add the Windows ROOT store CI job, a refused certificate failing examples/openkal, the openkal README notes and the bcrypt link request for MSVC. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for e4ee822 - Browse repository at this point
Copy the full SHA e4ee822View commit details -
Merge master (certificate verification, mcpplibs#21) into the proxy b…
…ranch The two changes meet in TlsSocket and in HttpClient::open_connection, and the conflicts are resolved here without changing what either side meant: * the move constructor and move assignment carry both the lower session (`lower_`, this branch) and the failure reason (`error_`, mcpplibs#21); * the failure paths of setup_tls take mcpplibs#21's form, `return fail(reason)`; * a connection that could not be opened reports the proxy's refusal when there is one, else the TLS session's reason, else `Connection failed`; * CHANGELOG keeps both entries under Unreleased. What the combination needs beyond resolving the text follows in the next commit. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for 6c59c7e - Browse repository at this point
Copy the full SHA 6c59c7eView commit details -
0.3.3 --- the proxy hop is verified like the target hop, and says why…
… it was refused What the certificate fix and the proxy branch need of each other beyond the text the merge resolved: * TlsSocket::fail() closes the transport with drop_transport(), so a handshake that fails inside a tunnel closes the session to the proxy as well, not only the descriptor a tunnelled session does not use. * connect_over(lower) clears the previous failure reason, as connect() and connect_over(Socket&&) do. * A TLS connection to an https:// proxy that fails reports the session's reason after the hop, `proxy: could not open a TLS connection to <proxy>: certificate verification failed: ...`. Without it the refusal mcpplibs#21 exists to explain reached the caller with the reason dropped. test_proxy gains the case: an https proxy whose certificate has no trusted issuer is refused with the reason, and receives no CONNECT. It fails without the proxy.cppm change. The version is 0.3.3 rather than 0.4.0. mcpp reads `tinyhttps = "0.3.0"` as ^0.3.0, which stops below 0.4.0, so only a patch release reaches the consumers that need the verification fix without editing a manifest. CHANGELOG states the fail-closed behaviour change first. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for d48aba1 - Browse repository at this point
Copy the full SHA d48aba1View commit details -
Merge mcpplibs#22: proxy URLs: credentials, https:// proxies and SOCK…
…S5 (0.3.3) Proxy authentication, https:// proxies and SOCKS5; contributor commits by Cloud_Yun. Maintainer commits merge master (mcpplibs#21) into the branch, verify the proxy hop and report its refusal reason, and set the version to 0.3.3. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for f461940 - Browse repository at this point
Copy the full SHA f461940View commit details -
0.3.4 --- a request in flight can be cancelled with a std::stop_token (…
…mcpplibs#23) send, send_stream and download_to_file take an optional std::stop_token as their last argument. Stopping it from another thread ends the call within about 50 ms and closes the connection; HttpResponse::cancelled and DownloadToFileResult::cancelled say so. A cancelled request is not retried and its redirect is not followed. Without a token nothing changes. With a token every wait on the socket is a poll in slices of at most 50 ms, the connect is checked before each address, and bio_recv waits before recv, so the TLS handshake and an HTTP, https or SOCKS5 proxy's exchange are covered. The token belongs to its call: it is set on the socket at the bottom of the connection (beneath an https:// proxy's tunnel, where the waits are) and taken off when the connection goes back to the pool. Where the C library is musl the TLS random generator is seeded from getentropy; above openkal on x86_64-windows-musl mbedTLS's /dev/urandom does not exist and every handshake failed. CI: Linux under gcc 16 and llvm 22, macOS arm64, the hermetic tests on Windows (msvc, llvm), and examples/openkal on x86_64-linux-gnu, x86_64-linux-musl, aarch64-linux-musl and x86_64-windows-musl. mcpp 2026.9.30.2. Design and plan: .agents/docs/design-cancel-stop-token.md, .agents/docs/exec-plan-0.3.4-cancel.md.
Configuration menu - View commit details
-
Copy full SHA for 156edeb - Browse repository at this point
Copy the full SHA 156edebView commit details -
CHANGELOG: 0.3.4 reaches a caret range, not a bare version; record th…
…e release in the plan A bare version is exact in mcpp, and "0.3.x" is not a form it accepts; measured against the published index, "^0.3.1" resolves to 0.3.4 under both mirrors and "0.3.1" stays at 0.3.1.
Configuration menu - View commit details
-
Copy full SHA for 2cc7310 - Browse repository at this point
Copy the full SHA 2cc7310View commit details
Commits on Oct 9, 2026
-
Bound the TLS handshake with connectTimeoutMs (mcpplibs#25)
After the TCP connect the socket is blocking, and bio_recv called recv without waiting unless a stop token was attached, so a server or an https:// proxy that accepted the connection and never sent its ServerHello held send(), send_stream() and download_to_file() for good. setup_tls sets a deadline of connectTimeoutMs on the socket at the bottom for the duration of the handshake; bio_recv waits against it (and against the token, if any), and a handshake that runs out of time fails with "TLS handshake timed out". It covers the target, an https:// proxy, and the target inside an https:// proxy's tunnel. A wait that a signal ends early is waited again; the deadline is hit only when the clock has passed it. TlsSocket::connect_over takes a trailing handshakeTimeoutMs (-1, the default, waits without limit); TlsSocket::connect bounds the handshake with the timeout it already took. Socket gains set_deadline, deadline_hit and wait_before_recv. CI: the openkal job on Windows finds Git for Windows's CA bundle instead of naming mingw64/ (Git 2.56 moved it under ucrt64/), and the Windows job runs test_handshake_timeout. Co-authored-by: Sunrisepeak <speakshen@163.com>
Configuration menu - View commit details
-
Copy full SHA for 9d4315e - Browse repository at this point
Copy the full SHA 9d4315eView commit details -
Add HttpClientConfig::extraCaFile to trust extra CA certificates (mcp…
…plibs#24) SSL_CERT_FILE replaces the default store, so trusting a private CA or a TLS-inspecting proxy meant building a combined bundle by hand. The new field names a PEM file whose certificates are added to the default store. It applies to the target connection and to the connection to an https:// proxy. A file that cannot be read or holds no certificate fails the connection and the message names the path; it is not skipped. proxy_tunnel takes the path as a trailing default argument and TlsSocket gains set_extra_ca_file. With the field empty nothing changes.
Configuration menu - View commit details
-
Copy full SHA for a0f7749 - Browse repository at this point
Copy the full SHA a0f7749View commit details -
0.3.5 --- the TLS handshake has a time limit, and extra CA certificat…
…es can be trusted The handshake is bounded by connectTimeoutMs (mcpplibs#25), and HttpClientConfig::extraCaFile adds a PEM file of roots to the default store (mcpplibs#24). A patch release: "^0.3.1" resolves to it. The plan, with the review of both PRs and the CI failure that Git for Windows 2.56 caused, is in .agents/docs/exec-plan-0.3.5.md.
Configuration menu - View commit details
-
Copy full SHA for 6153cdd - Browse repository at this point
Copy the full SHA 6153cddView commit details -
Configuration menu - View commit details
-
Copy full SHA for a312f63 - Browse repository at this point
Copy the full SHA a312f63View commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff master...master