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
72 lines
2.2 KiB
Go
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")
|
|
}
|
|
})
|
|
}
|