1 package webserver_test
2
3 import (
4 "context"
5 "io"
6 "net/http"
7 "net/http/httptest"
8 "strings"
9 "testing"
10
11 jsoniter "github.com/json-iterator/go"
12
13 "github.com/cybertec-postgresql/pgwatch/v6/internal/webserver"
14 "github.com/stretchr/testify/assert"
15 )
16
17 type Credentials struct {
18 User string `json:"user"`
19 Password string `json:"password"`
20 }
21
22 type ReadyBool bool
23
24 func (ready *ReadyBool) Ready() bool {
25 return bool(*ready)
26 }
27
28 func TestWebDisableOpt(t *testing.T) {
29 var ready ReadyBool
30 restsrv, err := webserver.Init(context.Background(), webserver.CmdOpts{WebDisable: "all"}, nil, nil, &ready)
31 assert.Nil(t, restsrv, "no webserver should be started")
32 assert.NoError(t, err)
33
34 restsrv, err = webserver.Init(context.Background(), webserver.CmdOpts{WebAddr: "127.0.0.1:8079", WebDisable: "ui"}, nil, nil, &ready)
35 assert.NotNil(t, restsrv)
36 assert.NoError(t, err)
37 r, err := http.Get("http://localhost:8079/")
38 assert.NoError(t, err)
39 assert.Equal(t, http.StatusNotFound, r.StatusCode, "no webui should be served")
40 r, err = http.Get("http://localhost:8079/liveness")
41 assert.NoError(t, err)
42 assert.Equal(t, http.StatusOK, r.StatusCode, "rest api should be served though")
43
44 restsrv, err = webserver.Init(context.Background(), webserver.CmdOpts{WebAddr: "127.0.0.1:8079"}, nil, nil, &ready)
45 assert.Nil(t, restsrv)
46 assert.Error(t, err, "port should be in use")
47 }
48
49 func TestHealth(t *testing.T) {
50 var ready ReadyBool
51 ctx, cancel := context.WithCancel(context.Background())
52 restsrv, _ := webserver.Init(ctx, webserver.CmdOpts{WebAddr: "127.0.0.1:8080"}, nil, nil, &ready)
53 assert.NotNil(t, restsrv)
54
55 r, err := http.Get("http://localhost:8080/liveness")
56 assert.NoError(t, err)
57 assert.Equal(t, http.StatusOK, r.StatusCode)
58
59 cancel()
60 r, err = http.Get("http://localhost:8080/liveness")
61 assert.NoError(t, err)
62 assert.Equal(t, http.StatusServiceUnavailable, r.StatusCode)
63
64 r, err = http.Get("http://localhost:8080/readiness")
65 assert.NoError(t, err)
66 assert.Equal(t, http.StatusServiceUnavailable, r.StatusCode)
67
68 ready = true
69 r, err = http.Get("http://localhost:8080/readiness")
70 assert.NoError(t, err)
71 assert.Equal(t, http.StatusOK, r.StatusCode)
72 }
73
74 func TestServerNoAuth(t *testing.T) {
75 host := "http://localhost:8081"
76 restsrv, _ := webserver.Init(context.Background(), webserver.CmdOpts{WebAddr: "localhost:8081"}, nil, nil, nil)
77 assert.NotNil(t, restsrv)
78 rr := httptest.NewRecorder()
79
80 reqOpts, err := http.NewRequest("OPTIONS", host, nil)
81 assert.NoError(t, err)
82 restsrv.Handler.ServeHTTP(rr, reqOpts)
83 assert.Equal(t, http.StatusOK, rr.Code)
84
85
86 rr = httptest.NewRecorder()
87 reqMetric, err := http.NewRequest("GET", host+"/metric", nil)
88 restsrv.Handler.ServeHTTP(rr, reqMetric)
89 assert.NoError(t, err)
90 assert.Equal(t, http.StatusUnauthorized, rr.Code, "REQUEST WITHOUT AUTHENTICATION")
91
92
93 rr = httptest.NewRecorder()
94 reqDb, err := http.NewRequest("GET", host+"/source", nil)
95 assert.NoError(t, err)
96 restsrv.Handler.ServeHTTP(rr, reqDb)
97 assert.Equal(t, http.StatusUnauthorized, rr.Code, "REQUEST WITHOUT AUTHENTICATION")
98
99
100 rr = httptest.NewRecorder()
101 reqLog, err := http.NewRequest("GET", host+"/log", nil)
102 assert.NoError(t, err)
103 restsrv.Handler.ServeHTTP(rr, reqLog)
104 assert.Equal(t, http.StatusUnauthorized, rr.Code, "REQUEST WITHOUT AUTHENTICATION")
105
106
107 rr = httptest.NewRecorder()
108 reqConnect, err := http.NewRequest("GET", host+"/test-connect", nil)
109 assert.NoError(t, err)
110 restsrv.Handler.ServeHTTP(rr, reqConnect)
111 assert.Equal(t, http.StatusUnauthorized, rr.Code, "REQUEST WITHOUT AUTHENTICATION")
112 }
113
114 func TestGetToken(t *testing.T) {
115 host := "http://localhost:8082"
116 restsrv, _ := webserver.Init(context.Background(), webserver.CmdOpts{WebAddr: "localhost:8082"}, nil, nil, nil)
117 rr := httptest.NewRecorder()
118
119 credentials := Credentials{
120 User: "admin",
121 Password: "admin",
122 }
123
124 payload, err := jsoniter.ConfigFastest.Marshal(credentials)
125 assert.NoError(t, err)
126
127 reqToken, err := http.NewRequest("POST", host+"/login", strings.NewReader(string(payload)))
128 assert.Equal(t, err, nil)
129
130 restsrv.Handler.ServeHTTP(rr, reqToken)
131
132 assert.Equal(t, rr.Code, http.StatusOK, "TOKEN RESPONSE OK")
133
134 token, err := io.ReadAll(rr.Body)
135 assert.Equal(t, err, nil)
136 assert.NotEqual(t, token, nil)
137 }
138