2026-07-22 17:55:45 +02:00
|
|
|
//SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
|
//SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
2025-11-02 15:00:53 +01:00
|
|
|
|
|
|
|
|
export module Crafter.Network;
|
|
|
|
|
|
|
|
|
|
export import :ClientTCP;
|
|
|
|
|
export import :ListenerTCP;
|
|
|
|
|
export import :ClientHTTP;
|
|
|
|
|
export import :ListenerHTTP;
|
2026-05-06 04:06:17 +02:00
|
|
|
export import :HTTP;
|
|
|
|
|
export import :ClientQUIC;
|
2026-05-19 02:53:50 +02:00
|
|
|
export import :ListenerQUIC;
|
|
|
|
|
export import :WebTransport;
|
|
|
|
|
#ifndef CRAFTER_NETWORK_BROWSER
|
|
|
|
|
// Exposed so user code can build WebTransport clients by hand against a
|
|
|
|
|
// ClientQUIC until we ship a ClientWebTransport wrapper. Most callers do
|
|
|
|
|
// not need the HTTP/3 frame helpers directly. Excluded from the browser
|
|
|
|
|
// build — HTTP3 uses throw and the wasm target runs with -fno-exceptions.
|
|
|
|
|
export import :HTTP3;
|
feat(http1): add an HTTP/1.1 client and listener
HTTP/3-only is not a deployable position yet: plenty of clients, proxies
and CI tooling still speak nothing but HTTP/1.1. This adds that path
using the request/response types the HTTP/3 stack already uses, so a
route handler or call site moves between the two protocols by changing
the class name.
- :HTTP1 — transport-free wire format. Serialisation with the framing
headers owned by the serialiser, and an incremental parser that takes
arbitrary socket chunks and yields one message at a time: keep-alive,
pipelining, content-length and chunked bodies (with trailers),
read-to-EOF responses, interim 1xx skipping, HEAD/204/304 framing and
Expect: 100-continue. Ambiguous framing is rejected rather than
guessed at (content-length with transfer-encoding, disagreeing
content-lengths, whitespace before a colon), and CR/LF in a value we
are asked to serialise is refused.
- ClientHTTP1 — persistent connection, redialling once when a pooled
connection turns out to have been closed by the peer, which is the
race HTTP/1.1 keep-alive cannot avoid. Nothing is replayed after a
response byte has arrived.
- ListenerHTTP1 — one thread per connection (keep-alive connections are
idle most of their life and would pin every ThreadPool thread),
automatic Date, HEAD, 100-continue, handler-requested close, idle and
request timeouts, and 400/404/500 responses. Routes fall back to the
query-stripped path so `/thing?x=1` reaches the handler for `/thing`.
No TLS: this is `http://` only. Encrypted traffic still goes over
HTTP/3, or through a TLS-terminating proxy.
Tests: codec unit tests including the malformed inputs above, a
client/server round-trip, keep-alive and stale-connection recovery, a
10 MiB body both ways, and interop both directions against curl and
python3's http.server (skipped when those are not installed).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 00:45:09 +00:00
|
|
|
// HTTP/1.1 over TCP, for peers that are not ready for HTTP/3. Native only:
|
|
|
|
|
// in the browser this job is already done by fetch() behind :ClientHTTP,
|
|
|
|
|
// and these partitions use exceptions and POSIX sockets.
|
|
|
|
|
export import :HTTP1;
|
|
|
|
|
export import :ClientHTTP1;
|
|
|
|
|
export import :ListenerHTTP1;
|
2026-05-19 02:53:50 +02:00
|
|
|
#endif
|