The ws/wss transport carries a raw byte stream (yamux), but the
golang.org/x/net/websocket Conn defaults to text frames (PayloadType
TextFrame). Per RFC 6455 §5.6 a text frame must contain valid UTF-8, so
RFC-compliant intermediaries (API gateways / reverse proxies) validate
the payload and close the connection when the binary tunnel data is not
valid UTF-8.
This goes unnoticed peer-to-peer because x/net/websocket does not
validate UTF-8 on read, but it breaks the connection through a compliant
validating proxy. Set PayloadType to BinaryFrame on both the server
listener and the client dialer so the tunnel is framed as binary.
Move the frps dashboard Clients and Proxies views to the paginated
/api/v2/clients and /api/v2/proxies endpoints instead of fetching all
data at once, and extend server-side proxy search so the search box
keeps working under pagination.
Frontend:
- Add V2Envelope/V2Page types and getV2 HTTP helper to api/http.ts
- Add v2 paginated fetch functions to api/client.ts and api/proxy.ts
- Add ClientV2Info and ProxyV2Info types for v2 API responses
- Rewrite Clients.vue with server-side pagination, status/user search
filtering, and ElPagination component
- Rewrite Proxies.vue with server-side pagination, type tabs, client
dropdown filter, and a search box that passes q to the API
- Default page size 10, selectable sizes [10, 20, 50, 100]
Backend:
- Extend /api/v2/proxies q matching to also cover online proxy spec
fields: TCP/UDP remotePort and HTTP/HTTPS/TCPMux customDomains and
subdomain, so dashboard search no longer needs to scan every page
- Add controller_v2 tests for the new spec-field matching
SUDP payload codec follows transport wireProtocol; same-protocol v1/v1 and v2/v2 keep raw join; only mixed proxy/visitor protocols use message-aware bridge; no new capability/selection field.
* auth/oidc: cache OIDC access token and refresh before expiry
- Use Config.TokenSource(ctx) once at init to create a persistent
oauth2.TokenSource that caches the token and only refreshes on expiry
- Wrap with oauth2.ReuseTokenSourceWithExpiry for configurable early refresh
- Add tokenRefreshAdvanceDuration config option (default: 300s)
- Add unit test verifying token caching with mock HTTP server
* address review comments
* auth/oidc: fallback to per-request token fetch when expires_in is missing
When an OIDC provider omits the expires_in field, oauth2.ReuseTokenSource
treats the cached token as valid forever and never refreshes it. This causes
server-side OIDC verification to fail once the JWT's exp claim passes.
Add a nonCachingTokenSource fallback: after fetching the initial token, if
its Expiry is the zero value, swap the caching TokenSource for one that
fetches a fresh token on every request, preserving the old behavior for
providers that don't return expires_in.
* auth/oidc: fix gosec lint and add test for zero-expiry fallback
Suppress G101 false positive on test-only dummy token responses.
Add test to verify per-request token fetch when expires_in is missing.
Update caching test to account for eager initial token fetch.
* fix lint
* test/e2e: replace sleeps with event-driven waits in chaos/group/store tests
Replace 21 time.Sleep calls with deterministic waiting using
WaitForOutput, WaitForTCPReady, and a new WaitForTCPUnreachable helper.
Add CountOutput method for snapshot-based incremental log matching.
* test/e2e: validate interval and cap dial/sleep to remaining deadline in WaitForTCPUnreachable
* test/e2e: replace RunProcesses client sleep with log-based proxy readiness detection
Replace the fixed 1500ms sleep in RunProcesses with event-driven proxy
registration detection by monitoring frpc log output for "start proxy
success" messages.
Key changes:
- Add thread-safe SafeBuffer to replace bytes.Buffer in Process, enabling
concurrent read/write of process output during execution
- Add Process.WaitForOutput() to poll process output for pattern matches
with timeout and early exit on process termination
- Add waitForClientProxyReady() that uses config.LoadClientConfig() to
extract proxy names, then waits for each proxy's success log
- For visitor-only clients (no deterministic readiness signal), fall back
to the original sleep with elapsed time deducted
* test/e2e: use shared deadline for proxy readiness and fix doc comment
- Use a single deadline in waitForClientProxyReady so total wait across
all proxies does not exceed the given timeout
- Fix WaitForOutput doc comment to accurately describe single pattern
with count semantics
* test/e2e: optimize RunFrps/RunFrpc with process exit detection
Refactor Process to track subprocess lifecycle via a done channel,
replacing direct cmd.Wait() in Stop() to avoid double-Wait races.
RunFrps/RunFrpc now use select on the done channel instead of fixed
sleeps, allowing short-lived processes (verify, startup failures) to
return immediately while preserving existing timeout behavior for
long-running daemons.
* test/e2e: guard Process against double-Start and Stop-before-Start
Add started flag to prevent double-Start panics and allow Stop to
return immediately when the process was never started. Use sync.Once
for closing the done channel as defense-in-depth against double close.