1248 Commits

Author SHA1 Message Date
yusing
d77f6960ec fix(route): handle synthetic load balancer routes consistently
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.
2026-03-11 11:45:53 +08:00
yusing
0bd134cf47 Apply compat patch 2026-03-10 15:01:07 +08:00
yusing
291fe67c31 chore(deps): update Go to 1.26.1 and upgrade dependencies across monorepo
- 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
2026-03-10 12:19:25 +08:00
yusing
93263eedbf feat(route): add support for relaying PROXY protocol header to TCP upstreams
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
2026-03-10 12:04:07 +08:00
yusing
41de86de75 fix(middleware): gate only body response modifiers
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.
2026-03-10 12:04:05 +08:00
yusing
59238adb5b fix(middleware): skip body rewriters when buffering fails
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.
2026-03-01 03:40:43 +08:00
yusing
5f48f141ca fix(systeminfo): Collect all partitions then filter partitions
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.
2026-02-28 18:16:04 +08:00
yusing
a0adc51269 feat(rules): support multiline or |
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.
2026-02-28 18:16:04 +08:00
yusing
c002055892 chore(rules): update example to use new block syntax 2026-02-28 18:16:03 +08:00
yusing
d5406fb039 doc(entrypoint): escape [] in mermaid 2026-02-28 18:16:03 +08:00
Jarek Krochmalski
1bd8b5a696 fix(middleware): restore SSE streaming for POST endpoints (regression in v0.27.0) (#206)
* 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>
2026-02-28 17:15:41 +08:00
yusing
b64944cfc3 fix(rules): add nil guard to entrypoint retrieval in route command 2026-02-25 12:04:34 +08:00
yusing
6576b7640a chore(deps: update dependencies 2026-02-24 18:14:39 +08:00
yusing
9ca2983a52 docs(rules): document new dynamic variables and redaction 2026-02-24 18:11:35 +08:00
yusing
ed2ca236b0 feat(api): accept rule config block string in playground
Update playground request to take rules as a string and parse
either YAML list or DSL config, with tests and swagger updates.
2026-02-24 18:11:17 +08:00
yusing
0eba045104 feat(rules): add $redacted dynamic variable for masking sensitive values
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.
2026-02-24 15:17:28 +08:00
yusing
77f2779114 fix(rules): expand nested function args
Allow $func(...) expressions inside function arguments by
extracting nested calls and expanding them before evaluation.
2026-02-24 15:15:42 +08:00
Yuzerion
d2d686b4d1 feat(rules): introduce block DSL, phase-based execution (#203)
* 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
2026-02-24 10:44:47 +08:00
yusing
169358659a refactor(middleware): improve response body modification gating
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.
2026-02-23 23:46:41 +08:00
yusing
0850ea3918 docs(http): remove default client from README.md 2026-02-23 14:51:30 +08:00
yusing
3001417a37 fix(health): only send recovery notification after down notification
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.
2026-02-23 11:05:19 +08:00
yusing
f6a82a3b7c docs(api): update swagger docs with field descriptions and operationId rename
- 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
2026-02-22 19:54:56 +08:00
yusing
4e5ded13fb fix(api/proxmox): add websocket validation to journalctl and tail endpoints
Add required websocket check at the beginning of both journalctl and tail endpoint handlers to ensure these endpoints only accept websocket connections.
2026-02-22 19:54:09 +08:00
yusing
4580543693 refactor(icons): improve favicon fetching with custom HTTP client and content-type validation
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.
2026-02-22 16:06:13 +08:00
yusing
bf54b51036 chore(http): remove stale default_client.go 2026-02-22 16:05:30 +08:00
yusing
8ba937ec4a refactor(middleware): replace sensitive fields with redacted types 2026-02-22 16:05:02 +08:00
yusing
0f78158c64 refactor: fix lint errors; improve error handling 2026-02-22 16:04:25 +08:00
yusing
3a7d1f8b18 refactor: modernize code with go fix 2026-02-21 13:03:21 +08:00
yusing
64ffe44a2d refactor(systeminfo): correct field usage regarding update to gopsutil submodule 2026-02-21 13:00:00 +08:00
yusing
dea37a437b chore: apply golangci-lint fmt 2026-02-21 12:56:51 +08:00
yusing
ee973f7997 chore(deps): upgrade dependencies and submodules 2026-02-21 12:53:34 +08:00
yusing
8756baf7fc fix(docs): remove application/json from /file/content API 2026-02-18 19:13:00 +08:00
yusing
a12bdeaf55 refactor(middleware): replace path prefix checks with function-based approach
Replace simple path prefix-based enforcement/bypass mechanism with a more
flexible function-based approach. This allows for more complex conditions
to determine when middleware should be enforced or bypassed.

- Add checkReqFunc and checkRespFunc types for flexible condition checking
- Replace enforcedPathPrefixes with separate enforce and bypass check functions
- Add static asset path detection for automatic bypassing
- Separate request and response check logic for better granularity
2026-02-18 19:12:07 +08:00
yusing
add7884a36 feat(icons): improve search ranking with priority-based matching
Restructure icon search to use a tiered ranking system:
- Exact matches get highest priority (rank 0)
- Prefix matches ranked by name length (rank 100+)
- Contains matches ranked by relevance (rank 500+)
- Fuzzy matches as fallback (rank 1000+)

Also refactors InitCache to use switch statements for clarity
and updates goutils submodule.
2026-02-18 18:13:34 +08:00
yusing
115fba4ff4 feat(route): allow empty listening port in port specification
Support the ":proxy" format where only the proxy port is specified.
When the listening port part is empty, it defaults to 0 instead of
returning a parse error.
2026-02-18 14:37:23 +08:00
yusing
bb757b2432 refactor: replace custom helper with stdlib strings.* 2026-02-18 14:26:29 +08:00
yusing
20695c52e8 docs: unify header to import path for package docs 2026-02-18 03:25:32 +08:00
yusing
7baf0b6fe5 refactor(metrics): reorganize system info collection into separate functions
Split the monolithic AllSystemInfo handler into smaller, focused functions:
- Extract streamSystemInfo for channel consumption
- Add queueSystemInfo for safe non-blocking queue operations
- Create collectSystemInfoRound for parallel agent data collection
- Implement handleRoundResult for consistent round result processing
- Replace custom exponential backoff with cenkalti/backoff/v5 library

This improves code maintainability and separates concerns within the metrics API endpoint.
2026-02-16 20:19:18 +08:00
yusing
9064a37d62 fix(rules): update webui rules manifest path from webmanifest to json
- Changed the path for the manifest from /manifest.webmanifest to /manifest.json in both webui_dev.yml and webui.yml.
2026-02-16 07:44:51 +08:00
yusing
f8bc8dddb6 refactor(icons): hasIcon always return true in tests 2026-02-15 20:08:10 +08:00
yusing
54ea4d8790 refactor(entrypoint): enhance Entrypoint interface with detailed comments 2026-02-15 20:08:10 +08:00
yusing
fbb8a1fca4 refactor(middleware): emit OIDC blocked event at specific error points 2026-02-15 20:08:10 +08:00
yusing
af62ac98d3 refactor(middleware): clone middleware definitions before modification
- This change enhances the integrity of middleware configurations by ensuring original definitions remain unchanged.
2026-02-15 20:08:10 +08:00
yusing
cc516d23db refactor(health): allow connection reuse in HTTP pinger
- Commented out the SetConnectionClose method to enable connection reuse for HTTP requests, improving performance.
- This is a follow up commit to be9af03a1e setting MaxConnsPerHost to 1000
2026-02-15 20:08:10 +08:00
yusing
f92e96831c fix(auth): reorder password validation to enhance security against timing attacks
- Always perform bcrypt comparison before checking the username to mitigate potential timing attack vulnerabilities.
2026-02-15 20:08:10 +08:00
yusing
154149b06d refactor: minor styling fixes; deadcode cleanup and correct log level 2026-02-15 20:08:09 +08:00
yusing
0a139067b8 fix(acl): add logging for unexpected remote address types in TCP and UDP listeners 2026-02-15 17:22:53 +08:00
yusing
be9af03a1e fix(health): increase MaxConnsPerHost for HTTP pinger
Updated the MaxConnsPerHost setting from 1 to 1000 in the HTTP pinger configuration.

Fixes "no free connections available to host" error
2026-02-15 17:22:10 +08:00
yusing
898002a38e feat(acl): add reason field to ACL logging for decision tracking
Add a reason parameter throughout the ACL system to track and log why
each IP was allowed or denied. This provides better visibility into
ACL decisions by recording specific reasons such as "allowed by
allow_local rule", "blocked by deny rule: [rule]", or "deny by default".

Changes include:
- Add reason field to checkCache and ipLog structs
- Update LogACL interface and implementations to accept reason
- Generate descriptive reasons for all ACL decision paths
- Include reason in console log output
2026-02-15 17:20:54 +08:00
yusing
0acedb034a feat: add event emission for blocked requests and provider changes
- Emit ACL blocked events with matched rule information
- Emit HTTP blocked events from CIDR whitelist, ForwardAuth, and OIDC middlewares
- Emit global events for provider file/docker changes
- Add MatchedIndex method to ACL matchers for rule identification
- Update goutils submodule for events package update
2026-02-15 16:48:39 +08:00