Add Certificates page and Traefik API frontend client
This commit is contained in:
parent
9e4c612dcb
commit
7fc90524b5
40 changed files with 6585 additions and 359 deletions
547
backend/internal/traefik/client_http_test.go
Normal file
547
backend/internal/traefik/client_http_test.go
Normal file
|
|
@ -0,0 +1,547 @@
|
|||
package traefik
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNewClient_Validation(t *testing.T) {
|
||||
_, err := NewClient("")
|
||||
if err == nil {
|
||||
t.Fatal("expected error for empty baseURL")
|
||||
}
|
||||
_, err = NewClient("not-a-url")
|
||||
if err == nil {
|
||||
t.Fatal("expected error for invalid baseURL")
|
||||
}
|
||||
c, err := NewClient("http://traefik:8080")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if c.baseURL != "http://traefik:8080" {
|
||||
t.Fatalf("baseURL mismatch: %q", c.baseURL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_Prefix(t *testing.T) {
|
||||
c, _ := NewClient("http://traefik:8080", WithPathPrefix("/dashboard"))
|
||||
if c.endpoint("/api/healthz") != "http://traefik:8080/dashboard/api/healthz" {
|
||||
t.Fatalf("prefix endpoint mismatch: %q", c.endpoint("/api/healthz"))
|
||||
}
|
||||
c2, _ := NewClient("http://traefik:8080/", WithPathPrefix("custom/"))
|
||||
if c2.endpoint("/api/routers") != "http://traefik:8080/custom/api/routers" {
|
||||
t.Fatalf("prefix trim mismatch: %q", c2.endpoint("/api/routers"))
|
||||
}
|
||||
// prefix ending with /api should not double
|
||||
c3, _ := NewClient("http://traefik:8080", WithPathPrefix("/dashboard/api"))
|
||||
if c3.endpoint("/api/routers") != "http://traefik:8080/dashboard/api/routers" {
|
||||
t.Fatalf("double api handling: %q", c3.endpoint("/api/routers"))
|
||||
}
|
||||
// no prefix
|
||||
c4, _ := NewClient("http://traefik:8080")
|
||||
if c4.endpoint("/api/entrypoints") != "http://traefik:8080/api/entrypoints" {
|
||||
t.Fatalf("no prefix: %q", c4.endpoint("/api/entrypoints"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetHealthz(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// New order tries /api/ping first
|
||||
if r.URL.Path != "/api/ping" && r.URL.Path != "/api/healthz" {
|
||||
t.Fatalf("unexpected path %q", r.URL.Path)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(HealthResponse{Status: "UP", Version: "3.7.0"})
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
resp, err := c.GetHealthz(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if resp.Status != "UP" {
|
||||
t.Fatalf("expected UP, got %q", resp.Status)
|
||||
}
|
||||
if resp.Version != "3.7.0" {
|
||||
t.Fatalf("version mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetHealthz_TextPlainOK(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
w.Write([]byte("OK"))
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
resp, err := c.GetHealthz(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if resp.Status != "OK" {
|
||||
t.Fatalf("expected OK, got %q", resp.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetHealthz_Fallback(t *testing.T) {
|
||||
// 404 on first two ping paths, success on /api/healthz
|
||||
hit := 0
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
hit++
|
||||
if r.URL.Path == "/api/ping" || r.URL.Path == "/ping" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
if r.URL.Path == "/api/healthz" {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte(`{"status":"UP"}`))
|
||||
return
|
||||
}
|
||||
http.NotFound(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
resp, err := c.GetHealthz(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if resp.Status != "UP" {
|
||||
t.Fatalf("expected UP from fallback, got %q", resp.Status)
|
||||
}
|
||||
if hit < 2 {
|
||||
t.Fatalf("expected at least 2 hits, got %d", hit)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetHealthz_All404(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
http.NotFound(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
_, err := c.GetHealthz(context.Background())
|
||||
if err == nil {
|
||||
t.Fatal("expected error when all paths 404")
|
||||
}
|
||||
if !IsNotFound(err) {
|
||||
t.Fatalf("expected IsNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetOverview_CamelCase(t *testing.T) {
|
||||
payload := `{
|
||||
"http": {"routers": {"total": 5, "warnings": 1, "errors": 0}, "services": {"total": 3, "warnings": 0, "errors": 0}, "middlewares": {"total": 2, "warnings": 0, "errors": 0}},
|
||||
"tcp": {"routers": {"total": 1, "warnings": 0, "errors": 0}, "services": {"total": 1, "warnings": 0, "errors": 0}, "middlewares": {"total": 0, "warnings": 0, "errors": 0}},
|
||||
"udp": {"routers": {"total": 0, "warnings": 0, "errors": 0}, "services": {"total": 0, "warnings": 0, "errors": 0}},
|
||||
"providers": ["docker", "file"],
|
||||
"totalRouters": 6,
|
||||
"totalServices": 4,
|
||||
"totalMiddlewares": 2,
|
||||
"traefikVersion": "3.7.0",
|
||||
"traefikCodename": "lascaux"
|
||||
}`
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/api/overview" {
|
||||
t.Fatalf("path %q", r.URL.Path)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte(payload))
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetOverview(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if got.TotalRouters != 6 {
|
||||
t.Fatalf("totalRouters expected 6, got %d", got.TotalRouters)
|
||||
}
|
||||
if got.TotalServices != 4 {
|
||||
t.Fatalf("totalServices expected 4, got %d", got.TotalServices)
|
||||
}
|
||||
if got.TotalMiddlewares != 2 {
|
||||
t.Fatalf("totalMiddlewares expected 2, got %d", got.TotalMiddlewares)
|
||||
}
|
||||
if got.TraefikVersion != "3.7.0" {
|
||||
t.Fatalf("traefikVersion expected 3.7.0, got %q", got.TraefikVersion)
|
||||
}
|
||||
if got.TraefikCodename != "lascaux" {
|
||||
t.Fatalf("traefikCodename expected lascaux, got %q", got.TraefikCodename)
|
||||
}
|
||||
if len(got.Providers) != 2 {
|
||||
t.Fatalf("providers expected 2, got %d", len(got.Providers))
|
||||
}
|
||||
// Ensure zero would fail if tags were snake_case
|
||||
if got.HTTP.Routers.Total != 5 {
|
||||
t.Fatalf("http routers total expected 5, got %d", got.HTTP.Routers.Total)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetEntrypoints_Slice(t *testing.T) {
|
||||
want := []Entrypoint{
|
||||
{Name: "web", Address: ":80"},
|
||||
{Name: "websecure", Address: ":443"},
|
||||
}
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/api/entrypoints" {
|
||||
t.Fatalf("path %q", r.URL.Path)
|
||||
}
|
||||
json.NewEncoder(w).Encode(want)
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetEntrypoints(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if len(got) != 2 || got[0].Name != "web" {
|
||||
t.Fatalf("unexpected: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetEntrypoints_Map(t *testing.T) {
|
||||
m := map[string]Entrypoint{
|
||||
"web": {Address: ":80"},
|
||||
"websecure": {Address: ":443"},
|
||||
}
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(m)
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetEntrypoints(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if len(got) != 2 {
|
||||
t.Fatalf("expected 2, got %d", len(got))
|
||||
}
|
||||
// Ensure names filled from map keys
|
||||
found := map[string]bool{}
|
||||
for _, ep := range got {
|
||||
found[ep.Name] = true
|
||||
}
|
||||
if !found["web"] || !found["websecure"] {
|
||||
t.Fatalf("missing names: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetRouters(t *testing.T) {
|
||||
routers := []Router{
|
||||
{Name: "api@docker", Provider: "docker", Rule: "Host(`example.com`)", EntryPoints: []string{"web"}, Service: "api@docker", Status: "enabled"},
|
||||
}
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(routers)
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetRouters(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if len(got) != 1 || got[0].Name != "api@docker" {
|
||||
t.Fatalf("unexpected: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetRouters_Fallback(t *testing.T) {
|
||||
routers := []Router{{Name: "web@docker", Provider: "docker", Rule: "Host(`a.com`)"}}
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/api/routers" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
if r.URL.Path == "/api/http/routers" {
|
||||
json.NewEncoder(w).Encode(routers)
|
||||
return
|
||||
}
|
||||
http.NotFound(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetRouters(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("fallback err: %v", err)
|
||||
}
|
||||
if len(got) != 1 || got[0].Name != "web@docker" {
|
||||
t.Fatalf("unexpected fallback: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetServices_WithMiddlewares(t *testing.T) {
|
||||
services := []Service{
|
||||
{Name: "my-service@docker", Provider: "docker", Type: "loadbalancer", Status: "enabled", Middlewares: []string{"auth@docker", "compress@docker"}},
|
||||
}
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Verify path and also test prefix handling
|
||||
if !strings.HasSuffix(r.URL.Path, "/api/services") && !strings.HasSuffix(r.URL.Path, "/api/http/services") {
|
||||
t.Fatalf("unexpected path %q", r.URL.Path)
|
||||
}
|
||||
json.NewEncoder(w).Encode(services)
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetServices(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if len(got) != 1 {
|
||||
t.Fatalf("expected 1 service")
|
||||
}
|
||||
if len(got[0].Middlewares) != 2 || got[0].Middlewares[0] != "auth@docker" {
|
||||
t.Fatalf("middlewares not decoded: %#v", got[0].Middlewares)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetServices_Map(t *testing.T) {
|
||||
m := map[string]Service{
|
||||
"svc1@docker": {Provider: "docker", Type: "loadbalancer", Status: "enabled"},
|
||||
}
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(m)
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetServices(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if len(got) != 1 || got[0].Name != "svc1@docker" {
|
||||
t.Fatalf("map conversion failed: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetMiddlewares(t *testing.T) {
|
||||
mws := []Middleware{{Name: "auth@docker", Provider: "docker", Type: "forwardAuth", Status: "enabled"}}
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(mws)
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetMiddlewares(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if len(got) != 1 || got[0].Type != "forwardAuth" {
|
||||
t.Fatalf("unexpected: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetProviders_StringSlice(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode([]string{"docker", "file", "kubernetes"})
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetProviders(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if len(got) != 3 || got[0].Name != "docker" {
|
||||
t.Fatalf("unexpected providers: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetProviders_ObjectSlice(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode([]Provider{{Name: "docker"}, {Name: "file"}})
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetProviders(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if len(got) != 2 {
|
||||
t.Fatalf("expected 2, got %d", len(got))
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetProviders_Map(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{"docker": struct{}{}, "file": struct{}{}})
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetProviders(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if len(got) != 2 {
|
||||
t.Fatalf("expected 2 from map, got %d", len(got))
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetCertificates(t *testing.T) {
|
||||
now := time.Now().UTC().Truncate(time.Second)
|
||||
certs := []Certificate{
|
||||
{
|
||||
Store: "default",
|
||||
Names: []string{"example.com", "www.example.com"},
|
||||
NotAfter: now.Add(24 * time.Hour),
|
||||
NotBefore: now.Add(-24 * time.Hour),
|
||||
Issuer: "CN=Test CA",
|
||||
SANs: []string{"example.com", "www.example.com"},
|
||||
SerialNumber: "123",
|
||||
},
|
||||
}
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/api/certificates" {
|
||||
t.Fatalf("path %q", r.URL.Path)
|
||||
}
|
||||
json.NewEncoder(w).Encode(certs)
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetCertificates(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if len(got) != 1 {
|
||||
t.Fatalf("expected 1 cert")
|
||||
}
|
||||
if got[0].Issuer != "CN=Test CA" {
|
||||
t.Fatalf("issuer mismatch: %q", got[0].Issuer)
|
||||
}
|
||||
if len(got[0].Names) != 2 || got[0].Names[0] != "example.com" {
|
||||
t.Fatalf("names mismatch: %#v", got[0].Names)
|
||||
}
|
||||
if len(got[0].SANs) != 2 {
|
||||
t.Fatalf("sans mismatch: %#v", got[0].SANs)
|
||||
}
|
||||
if !got[0].NotAfter.Equal(now.Add(24 * time.Hour)) {
|
||||
t.Fatalf("notAfter mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_GetCertificates_IssuerObject(t *testing.T) {
|
||||
// Traefik may return issuer as object
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte(`[{"store":"default","names":["a.com"],"notAfter":"2026-09-02T00:00:00Z","notBefore":"2025-09-02T00:00:00Z","issuer":{"commonName":"Test CA"},"sans":["a.com"]}]`))
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
got, err := c.GetCertificates(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if len(got) != 1 || got[0].Issuer != "Test CA" {
|
||||
t.Fatalf("expected issuer Test CA, got %#v", got[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_TypedErrors(t *testing.T) {
|
||||
cases := []struct {
|
||||
code int
|
||||
check func(error) bool
|
||||
name string
|
||||
}{
|
||||
{404, IsNotFound, "404"},
|
||||
{401, IsUnauthorized, "401"},
|
||||
{403, IsUnauthorized, "403"},
|
||||
{500, IsServerError, "500"},
|
||||
{502, IsServerError, "502"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(tc.code)
|
||||
w.Write([]byte(`{"message":"error"}`))
|
||||
}))
|
||||
c, _ := NewClient(ts.URL)
|
||||
_, err := c.GetRouters(context.Background())
|
||||
ts.Close()
|
||||
if err == nil {
|
||||
t.Fatalf("%s expected error", tc.name)
|
||||
}
|
||||
if !tc.check(err) {
|
||||
t.Fatalf("%s check failed for err %v", tc.name, err)
|
||||
}
|
||||
apiErr, ok := err.(*APIError)
|
||||
if !ok {
|
||||
t.Fatalf("%s not APIError", tc.name)
|
||||
}
|
||||
if apiErr.StatusCode != tc.code {
|
||||
t.Fatalf("%s status mismatch %d", tc.name, apiErr.StatusCode)
|
||||
}
|
||||
// Ensure non-matching checks are false
|
||||
if tc.code == 404 && IsServerError(err) {
|
||||
t.Fatalf("404 should not be server error")
|
||||
}
|
||||
if tc.code == 500 && IsNotFound(err) {
|
||||
t.Fatalf("500 should not be not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_Context(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
w.Write([]byte(`[]`))
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
_, err := c.GetRouters(ctx)
|
||||
if err == nil {
|
||||
t.Fatalf("expected context canceled error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "context canceled") {
|
||||
t.Fatalf("expected context canceled, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_WithPrefix(t *testing.T) {
|
||||
var gotPath string
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
gotPath = r.URL.Path
|
||||
json.NewEncoder(w).Encode([]Entrypoint{})
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL, WithPathPrefix("/my/prefix"))
|
||||
_, err := c.GetEntrypoints(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if gotPath != "/my/prefix/api/entrypoints" {
|
||||
t.Fatalf("expected prefix path, got %q", gotPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_CustomHeader(t *testing.T) {
|
||||
var gotAuth string
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
gotAuth = r.Header.Get("Authorization")
|
||||
json.NewEncoder(w).Encode([]Provider{})
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL, WithHeader("Authorization", "Bearer token123"))
|
||||
_, err := c.GetProviders(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if gotAuth != "Bearer token123" {
|
||||
t.Fatalf("header not sent: %q", gotAuth)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_InvalidJSON(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(`not json`))
|
||||
}))
|
||||
defer ts.Close()
|
||||
c, _ := NewClient(ts.URL)
|
||||
_, err := c.GetRouters(context.Background())
|
||||
if err == nil {
|
||||
t.Fatalf("expected decode error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "decode") {
|
||||
t.Fatalf("expected decode prefix, got %v", err)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue