diff options
| author | historia <[not public]> | 2026-10-05 18:16:47 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-10-05 18:16:47 -0400 |
| commit | 9d8c43cd68c960b9a6b8f781684f763e204a4498 (patch) | |
| tree | c9e2a02094a8700db29db2768a0d058ce259a4f4 /internal/net | |
| parent | 7a15a5d70004b28bf2a710fa0f536af2446e5b17 (diff) | |
| download | thehouseoficarus-9d8c43cd68c960b9a6b8f781684f763e204a4498.tar.gz | |
fix: shared YAML encoder and journal directory, text cleanup
Diffstat (limited to 'internal/net')
| -rw-r--r-- | internal/net/web_test.go | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/internal/net/web_test.go b/internal/net/web_test.go new file mode 100644 index 0000000..d16b31a --- /dev/null +++ b/internal/net/web_test.go @@ -0,0 +1,59 @@ +package net + +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/gorilla/websocket" +) + +// The browser transport previously had no tests. CheckOrigin is the security +// boundary for the /ws upgrade; test it directly with a non-loopback peer so +// the loopback bypass does not mask a hostile Origin. +func TestWebSocketCheckOrigin(t *testing.T) { + cases := []struct { + name string + origin string + host string + remoteAddr string + want bool + }{ + {"no origin", "", "mud.example:4000", "203.0.113.5:1234", true}, + {"same host", "http://mud.example:4000", "mud.example:4000", "203.0.113.5:1234", true}, + {"same host https", "https://mud.example:4000", "mud.example:4000", "203.0.113.5:1234", true}, + {"same hostname no port", "http://mud.example", "mud.example:4000", "203.0.113.5:1234", true}, + {"hostile origin", "http://evil.example", "mud.example:4000", "203.0.113.5:1234", false}, + {"loopback bypass", "http://evil.example", "mud.example:4000", "127.0.0.1:1234", true}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + req := &http.Request{Header: http.Header{}, Host: tc.host, RemoteAddr: tc.remoteAddr} + if tc.origin != "" { + req.Header.Set("Origin", tc.origin) + } + if got := upgrader.CheckOrigin(req); got != tc.want { + t.Fatalf("CheckOrigin(%q, host %q, peer %q) = %v, want %v", tc.origin, tc.host, tc.remoteAddr, got, tc.want) + } + }) + } +} + +// The /ws upgrade wires a live session and writer. Drive it end-to-end over a +// real HTTP test server (loopback, so the origin check passes). +func TestWebSocketUpgradeAccepted(t *testing.T) { + s := &Server{hub: NewHub()} + done := make(chan struct{}) + s.handler = func(*Session, string) { <-done } + srv := httptest.NewServer(newHTTPMux(s)) + defer srv.Close() + defer close(done) + + wsURL := "ws" + strings.TrimPrefix(srv.URL, "http") + "/ws" + conn, resp, err := websocket.DefaultDialer.Dial(wsURL, nil) + if err != nil { + t.Fatalf("upgrade rejected: %v (resp %v)", err, resp) + } + conn.Close() +} |
