645df52c0b
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 13s
CI / ui (pull_request) Successful in 32s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m8s
- Client IP: the compose caddy trusts X-Forwarded-For from private-range upstreams (trusted_proxies private_ranges), so the real client IP survives the host-caddy hop (it was logging the docker caddy hop 172.18.0.x for chat moderation and bucketing the gateway per-IP rate limiter on it). Correct and spoof-safe in both contours (prod has no host caddy); peerIP unit-tested. - Ad banner gated off behind a compile-time SHOW_AD_BANNER=false (the if-branch, the AdBanner import and banner.ts are tree-shaken out of the prod bundle). - Landing: the Telegram entry is just the 64px logo (clickable, no button/text). - TG-fullscreen header: title + menu centred as a pair (hamburger right of the title), pinned to the bottom of the TG nav band. - Edge-swipe back (Screen): a left-edge rightward drag navigates to back (touch/pen only, armed from <=24px; skipped inside Telegram). - Chat soft-keyboard: a bottom-sheet Modal lifted above the keyboard by a visualViewport-driven transform (compositor-only, no page/sheet relayout). iOS-specific, needs on-device tuning; native resize=none awaits Capacitor. - Tests: e2e for the in-game '✓ in friends' item and a board→board tile relocation; codec units for last_activity_unix + OutgoingRequestList. Deferred to the next PR (agreed): #4 enrich the your-turn/game-end push; #5 hide finished games from the lobby.
36 lines
1.1 KiB
Go
36 lines
1.1 KiB
Go
package connectsrv
|
|
|
|
import (
|
|
"net/http"
|
|
"testing"
|
|
)
|
|
|
|
// TestPeerIP covers the client-IP extraction the chat-moderation IP and the per-IP rate
|
|
// limiter both rely on: the first X-Forwarded-For hop (the real client, once Caddy is
|
|
// configured to trust its upstream), falling back to the connection peer (Stage 17).
|
|
func TestPeerIP(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
addr string
|
|
xff string
|
|
want string
|
|
}{
|
|
{"xff single", "10.0.0.1:5000", "203.0.113.7", "203.0.113.7"},
|
|
{"xff client then proxies", "10.0.0.1:5000", "203.0.113.7, 172.18.0.3", "203.0.113.7"},
|
|
{"xff trims spaces", "10.0.0.1:5000", " 203.0.113.9 , 10.0.0.2", "203.0.113.9"},
|
|
{"no xff uses peer host", "203.0.113.5:42000", "", "203.0.113.5"},
|
|
{"no xff no port", "203.0.113.6", "", "203.0.113.6"},
|
|
}
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
h := http.Header{}
|
|
if tc.xff != "" {
|
|
h.Set("X-Forwarded-For", tc.xff)
|
|
}
|
|
if got := peerIP(tc.addr, h); got != tc.want {
|
|
t.Errorf("peerIP(%q, xff=%q) = %q, want %q", tc.addr, tc.xff, got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|