Files
3x-ui-agent/internal/web/runtime/remote_mtls_test.go
T
Sanaei f727d04f65
Release 3X-UI for Docker / build (push) Canceled after 0s
Release 3X-UI / build (386) (push) Canceled after 0s
Release 3X-UI / build (amd64) (push) Canceled after 0s
Release 3X-UI / build (arm64) (push) Canceled after 0s
Release 3X-UI / build (armv5) (push) Canceled after 0s
Release 3X-UI / build (armv6) (push) Canceled after 0s
Release 3X-UI / build (armv7) (push) Canceled after 0s
Release 3X-UI / build (s390x) (push) Canceled after 0s
Release 3X-UI / Build for Windows (amd64) (push) Canceled after 0s
Release 3X-UI / Publish rolling dev release (push) Canceled after 0s
v3.7.0
2026-08-24 15:07:15 +02:00

72 lines
2.2 KiB
Go

package runtime
import (
"context"
"net/http"
"net/http/httptest"
"net/url"
"strconv"
"testing"
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
)
// nodeForPlainServer builds an http (non-TLS) node so do()'s token handling can
// be exercised without TLS scaffolding.
func nodeForPlainServer(t *testing.T, srv *httptest.Server, mode, token string) *model.Node {
t.Helper()
u, err := url.Parse(srv.URL)
if err != nil {
t.Fatalf("parse url: %v", err)
}
port, err := strconv.Atoi(u.Port())
if err != nil {
t.Fatalf("parse port: %v", err)
}
return &model.Node{
Id: 1, Name: "n1", Scheme: "http", Address: u.Hostname(), Port: port,
BasePath: "/", ApiToken: token, Enable: true, AllowPrivateAddress: true,
TlsVerifyMode: mode,
}
}
// TestRemoteDo_MTLSNodeNoBearer asserts that an mtls node with no API token
// sends its request with NO Authorization header and does not trip the
// empty-token precondition; while a non-mtls node with no token still errors.
func TestRemoteDo_MTLSNodeNoBearer(t *testing.T) {
var reached bool
var gotAuth string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
reached = true
gotAuth = r.Header.Get("Authorization")
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"success":true}`))
}))
defer srv.Close()
t.Run("mtls without token sends no Authorization header", func(t *testing.T) {
reached, gotAuth = false, "sentinel"
r := NewRemote(nodeForPlainServer(t, srv, "mtls", ""), nil)
if _, err := r.do(context.Background(), http.MethodGet, "ping", nil); err != nil {
t.Fatalf("mtls node with no token must not error on the token precondition: %v", err)
}
if !reached {
t.Fatal("request did not reach the server")
}
if gotAuth != "" {
t.Fatalf("Authorization header = %q, want empty for a tokenless mtls node", gotAuth)
}
})
t.Run("non-mtls without token still errors", func(t *testing.T) {
reached = false
r := NewRemote(nodeForPlainServer(t, srv, "verify", ""), nil)
if _, err := r.do(context.Background(), http.MethodGet, "ping", nil); err == nil {
t.Fatal("non-mtls node with no token must still error")
}
if reached {
t.Fatal("non-mtls tokenless request must not reach the server")
}
})
}