Synthetic load balancer routes were created with SchemeNone and a zero
proxy port, so the embedded Route logic treated them as excluded routes.
That caused them to be keyed like excluded routes instead of by alias,
which broke HTTP route lookup in reverse proxy load balancer tests.
Override Key and ShouldExclude for synthetic load balancer routes so
they stay addressable through the HTTP route pool while preserving the
existing behavior for normal backend routes.
Also guard addToLoadBalancer against a nil Homepage on an existing
linked route, and update the reverse proxy test to use the in-memory
test entrypoint rather than depending on real listener setup.
- Update golang base image in Dockerfiles from 1.26.0 to 1.26.1
- Upgrade go.mod go version to 1.26.1 in all modules
- Update github.com/yusing/godoxy from v0.26.0 to v0.27.2
- Update gin from v1.11.0 to v1.12.0, docker/cli to v29.3.0, gotify to v2.9.1
- Update golang.org/x/{net,oauth2,sync,time,sys} to latest versions
- Update OpenTelemetry packages to v1.42.0/v0.67.0
- Update OpenJDK and other cloud provider SDKs
- Update goutils submodule to latest commit
Add `relay_proxy_protocol_header` configuration option for TCP routes that enables
forwarding the original client IP address to upstream services via PROXY protocol
v2 headers. This feature is only available for TCP routes and includes validation
to prevent misuse on UDP routes.
- Add RelayProxyProtocolHeader field to Route struct with JSON tag
- Implement writeProxyProtocolHeader in stream package to craft v2 headers
- Update TCPTCPStream to conditionally send PROXY header to upstream
- Add validation ensuring feature is TCP-only
- Include tests for both enabled/disabled states and incoming proxy header relay
Replace the rewrite requirement check with a BodyResponseModifier
marker and treat header and body modifiers separately.
This ensures header/status rewrites still apply when body rewriting is
blocked (for binary, encoded, or chunked responses), while body changes
are skipped safely. It also avoids body reset/close side effects and
returns early on passthrough responses.
Update middleware tests to cover split header/body behavior and themed
middleware body-skip scenarios.
Prevent response modifiers that require body rewriting from running when
the body rewrite gate blocks buffering (for example, chunked transfer
encoding).
Add an explicit `requiresBodyRewrite` capability and implement it for
HTML/theme/error-page modifiers, including bypass delegation.
Also add a regression test to ensure the original response body remains
readable and is not closed prematurely when rewrite is blocked.
This commit fixeds the "http: read on closed response body" with empty page error
happens when body-rewriting middleware (like themed) runs on responses where body rewrite is blocked (e.g. chunked),
then the gate restores an already-closed original body.
Keep only real disk-like mounts (/, /dev/*,
and /mnt/* excluding /mnt/ itself and /mnt/wsl) to avoid noisy or irrelevant entries in
disk metrics.
Normalize disk map keys to use mountpoints for empty/none and /dev/root
devices so usage data remains stable and accessible across environments.
treat lines ending with unquoted `|` or `&` as continued
conditions in `do` block headers so nested blocks parse correctly
across line breaks.
update `on` condition splitting to avoid breaking on newlines that
follow an unescaped trailing pipe, while still respecting quotes,
escapes, and bracket nesting.
add coverage for multiline `|`/`&` continuations in `do` parsing,
`splitAnd`, `parseOn`, and HTTP flow nested block behavior.
* fix(middleware): restore SSE streaming for POST endpoints
Regression introduced in 16935865 (v0.27.0).
Before that commit, LazyResponseModifier only buffered HTML responses and
let everything else pass through via the IsBuffered() early return. The
refactor replaced it with NewResponseModifier which unconditionally buffers
all writes until FlushRelease() fires after the handler returns. That kills
real-time streaming for any SSE endpoint that uses POST.
The existing bypass at ServeHTTP line 193 only fires when the *request*
carries Accept: text/event-stream. That works for browser EventSource (which
always sets that header) but not for programmatic fetch() calls, which set
Content-Type: application/json on the request and only emit
Content-Type: text/event-stream on the *response*.
Fix: introduce ssePassthroughWriter, a thin http.ResponseWriter wrapper that
sits in front of the ResponseModifier. It watches for Content-Type:
text/event-stream in the response headers at the moment WriteHeader or the
first Write is called. Once detected it copies the buffered headers to the
real writer and switches all subsequent writes to pass directly through with
an immediate Flush(), bypassing the ResponseModifier buffer entirely.
Also tighten the Accept header check from == to strings.Contains so that
Accept: text/event-stream, */* is handled correctly.
Reported against Dockhand (https://github.com/Finsys/dockhand) where
container update progress, image pull logs and vulnerability scan output all
stopped streaming after users upgraded to GoDoxy v0.27.0. GET SSE endpoints
(container logs) continued to work because browsers send Accept:
text/event-stream for EventSource connections.
* fix(middleware): make Content-Type SSE check case-insensitive
* refactor(middleware): extract Content-Type into a named constant
* fix(middleware): enhance safe guard to avoid buffering SSE, WS and large bodies
Reverts some changes in 16935865 and apply more rubust handling.
Use a lazy response modifier that buffers only when the response is safe
to mutate. This prevents middleware from intercepting websocket/SSE
streams, encoded payloads, and non-text or oversized responses.
Set a 4MB max buffered size and gate buffering via response headers
(content type, transfer/content encoding, and content length). Skip
mutation when a response is not buffered or mutation setup fails, and
simplify chained response modifiers to operate on the same response.
Also update the goutils submodule for max body limit support.
---------
Co-authored-by: yusing <yusing.wys@gmail.com>
- Add script logic to create empty placeholder files for minified JS files
so go vet won't complain about missing files
- Run go mod tidy in root and agent directory to clean up dependencies
Add `set -euo pipefail` for strict error handling, check for clean working tree before running, and add trap for cleanup. Move sed replacements from patch file to actual changed Go files to correctly apply sonic-to-json transformations after checkout.
Introduces a new `$redacted` dynamic variable that wraps its single
argument with `strutils.Redact`, allowing sensitive values (e.g.,
authorization headers, query parameters) to be masked in rule
expressions.
The variable accepts exactly one argument, which may itself be a nested
dynamic variable expression such as `$header(Authorization)` or
`$arg(token)`, enabling patterns like `$redacted($header(Authorization))`.
Adds corresponding tests covering plain string redaction, nested header
and query arg wrapping, and the error case when no argument is provided.
The repoRootAbs was resolving to the script directory instead of the
repository root. Fixed by resolving two levels up from import.meta.dir.
Also optimized writeImplDocToMdx to skip writes when content is unchanged
and removed unused return value from syncImplDocs.
* chore(deps): update submodule goutils
* docs(http): remove default client from README.md
* refactor(rules): introduce block DSL, phase-based execution, and flow validation
- add block syntax parser/scanner with nested @blocks and elif/else support
- restructure rule execution into explicit pre/post phases with phase flags
- classify commands by phase and termination behavior
- enforce flow semantics (default rule handling, dead-rule detection)
- expand HTTP flow coverage with block + YAML parity tests and benches
- refresh rules README/spec and update playground/docs integration
- Default rules act as fallback handlers that execute only when no matching non-default rule exists in the pre phase
- IfElseBlockCommand now returns early when a condition matches with a nil Do block, instead of falling through to else blocks
- Add nil check for auth handler to allow requests when no auth is configured
* fix(rules): buffer log output before writing to stdout/stderr
* refactor(api/rules): remove IsResponseRule field from ParsedRule and related logic
* docs(rules): update examples to use block syntax
Refactor response body modification to only allow text-like content types
(JSON, YAML, XML, etc.) instead of all HTML responses.
Body modification is now
blocked for binary content and transfer/content encoded responses, while status
code and headers can still be modified.
This prevents issues with compressed or streaming responses while
maintaining the ability to modify text-based API responses.
Previously, up notifications were sent whenever a service recovered,
even if no down notification had been sent (e.g., when recovering
before the failure threshold was met). This could confuse users who
would receive "service is up" notifications without ever being
notified of a problem.
Now, recovery notifications are only sent when a prior down
notification exists, ensuring notification pairs are always complete.
- Add minimum: 0 validation to LogRetention properties (days, keep_size, last)
- Add "interned" descriptions to fstype, path, and name fields
- Rename operationId and x-id from "routes" to "list" for GET /route endpoint
Add required websocket check at the beginning of both journalctl and tail endpoint handlers to ensure these endpoints only accept websocket connections.
Add a new CLI application (`cmd/cli/`) that generates command-line interface commands from the API swagger specification. Includes:
- Main CLI entry point with command parsing and execution
- Code generator that reads swagger.json and generates typed command handlers
- Makefile targets (`gen-cli`, `build-cli`) for generating and building the CLI
- GitHub Actions workflow to build cross-platform CLI binaries (linux/amd64, linux/arm64)
Replace the existing HTTP client with a custom-configured client that skips TLS verification for favicon fetching,
and add explicit Content-Type validation to ensure only valid image responses are accepted.
This fixes potential issues with SSL certificate validation and prevents processing of non-image responses.