User-configured metadata on recorder objects (recorders[].metadata in YAML)
was silently discarded — MetadataRecordOption existed but was never called
anywhere in the codebase, causing plugin (HTTP/gRPC) recorders to always
receive null metadata.
Fix: wrap recorders that carry config metadata in MetadataRecorder, which
auto-appends the metadata to every Record() call. This covers all paths
(handler, router, sniffer, service) with zero call-site changes.
Add remote config fetching capability to the -C CLI flag, enabling
centralized fleet management of gost nodes.
- readConfig() now detects http:// and https:// URLs and fetches
them via HTTP GET with a 30s timeout and shared client pool
- Format auto-detection from Content-Type header (using mime
parsing) with fallback to URL path extension (.yaml/.json)
- 10 MiB response size limit to prevent memory exhaustion
- URL userinfo stripped from error messages for safety
- Fix ReadFile to force viper config type from file extension,
preventing format detection ambiguity
- Fix viper config search path fallback: skip cfg.Load() when
-C flags are explicitly provided, avoiding unwanted merges
- Tests: URL fetch (YAML/JSON), non-200, oversize, detectFormat,
isHTTPURL, sanitizeURL, and combined file+URL Parse scenario
Allow passing -C multiple times to load and merge several configuration
files in order. Slice fields are appended; scalar fields (TLS, Log, API,
Metrics, Profiling) are overridden by later files — the same semantics as
the existing mergeConfig() used for CLI+config merging.
- Change Args.CfgFile string to Args.CfgFiles []string
- Extract readConfig() helper from Parse() for single-source loading
- Loop over CfgFiles in Parse(), merging each into the accumulator
- Add Quotas to mergeConfig (was missing from the slice list)
- Add TestParse_MultiFile integration test for two-file merge
Closesgo-gost/gost#150
Adds RejectUnknownSNI and ServerNames fields to TLSConfig. When enabled,
TLS handshakes with missing or non-allowlisted SNI are rejected at the
handshake level via GetConfigForClient before any certificate is sent.
Works across all TLS-based listener types (tls, mtls, ws, mws, http2,
grpc, http3) since they share the same *tls.Config from LoadServerConfig.
- Add RewriteRequestBody field to HTTPNodeConfig (yaml: rewriteRequestBody)
- Add RewriteRequestBody field to HTTPNodeSettings in core chain
- Add rewriteReqBody function symmetric to rewriteRespBody in sniffer_rewrite.go
- Wire up rewriteReqBody call in httpRoundTrip before body wrapping for recording
- Add new RewriteResponseBody config field, deprecate old RewriteBody
- Parse both RewriteRequestBody and RewriteResponseBody in node config parsing
- Add 10 test cases covering nil, skip, content-type filter, and chained rewrites
- Bump core dependency to v0.4.1
- Fix: clone response header map in internal/util/sniffing/sniffer_http.go
tokenTransport now delegates CloseIdleConnections to the underlying
*http.Transport so http.Client.CloseIdleConnections() works through
the wrapper. Three plugin Close() methods updated to unwrap via
HTTPClientTransport before calling CloseIdleConnections.
RoundTrip now short-circuits when caller already set Authorization,
avoiding an unnecessary req.Clone allocation on the pass-through path.
Add godoc comments for all 62 exported symbols across 20 files in
config/parsing/: 23 MDKey constants, 35 Parse*/List/Default* functions,
3 TLS helpers, 1 Args struct with 7 fields, and the package doc.
Prevent data loss and nil panics across 5 parse functions:
- chain: nil-guard hop entries to avoid deref on empty YAML lists
- hop: build merged metadata map instead of writing inherited values
into the original NodeConfig; swap+restore around ParseNode call
- node: use local connCfg/dialCfg instead of overwriting cfg.Connector
and cfg.Dialer fields; only fill in Type when empty
- parser: preserve existing config file fields when env vars override
Level/Addr (was replacing the entire struct)
- router: only update ipNet from dst CIDR if parse succeeds, keeping
the route.Net fallback instead of overwriting with nil
- loader: guard cfg == nil in Load() to prevent nil-pointer dereference on
cfg.Log / cfg.TLS access.
- loader: defer logger.SetDefault and parsing.SetDefaultTLSConfig until
after register() succeeds, so a failed reload does not leave global
state (logger, default TLS) pointing at the new config while components
remain from the old config.
- loader: extract registerGroup[T] helper to eliminate repeated
unregister-then-register boilerplate. Entries are parsed and collected
before unregistering; a parse error now preserves the previous group
(old code unregistered first, then parsed, leaving an empty registry on
parse failure).
- hop: move cfg.SockOpts.Mark extraction outside the cfg.Metadata != nil
block so the socket mark is read even when hop-level metadata is absent.
- hop: fix copy-paste error in netns inheritance: v.Name was incorrectly
stored as MDKeyNetns instead of v.Netns (introduced in f71351f).
Upgrade github.com/go-gost/core from v0.3.3 to v0.4.0, adapting to
interface changes:
- Admit(ctx, network, addr, opts) now accepts a network parameter
- Router.Dial now accepts variadic chain.DialOption, forwarded to
the route's Dial call along with router-level options
- gRPC/HTTP admission plugins include the new Network field
Also fix two typos: ResoloverNodeOption -> ResolverNodeOption,
WithHostOpton -> WithHostOption.