| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- package api
- import (
- "bytes"
- "encoding/json"
- "net/http"
- "net/http/httptest"
- "path/filepath"
- "testing"
- "debtik/internal/auth"
- "debtik/internal/reverseproxy"
- )
- func setupTestProxyServer(t *testing.T) (*Server, *reverseproxy.Manager) {
- tmpDir := t.TempDir()
- cfgPath := filepath.Join(tmpDir, "reverse_proxy.json")
- proxyMgr := reverseproxy.NewManager(cfgPath, nil)
- authPath := filepath.Join(tmpDir, "users.json")
- authMgr := auth.NewManager(authPath)
- srv := &Server{
- proxyMgr: proxyMgr,
- authMgr: authMgr,
- mux: http.NewServeMux(),
- fsHandler: http.NotFoundHandler(),
- }
- srv.registerRoutes()
- return srv, proxyMgr
- }
- func TestProxyAPIEndpoints(t *testing.T) {
- srv, _ := setupTestProxyServer(t)
- // 1. GET /api/proxy/config
- req := httptest.NewRequest(http.MethodGet, "/api/proxy/config", nil)
- rec := httptest.NewRecorder()
- srv.mux.ServeHTTP(rec, req)
- if rec.Code != http.StatusOK {
- t.Fatalf("GET /api/proxy/config status = %d; want 200", rec.Code)
- }
- var cfg reverseproxy.Config
- if err := json.NewDecoder(rec.Body).Decode(&cfg); err != nil {
- t.Fatalf("failed to decode config: %v", err)
- }
- if !cfg.Enabled || cfg.HTTPPort != 80 {
- t.Errorf("unexpected config defaults: %+v", cfg)
- }
- // 2. POST /api/proxy/rules (Create Rule)
- newRule := reverseproxy.Rule{
- Name: "Web App",
- Enabled: true,
- Domains: []string{"app.example.com"},
- Path: "/app1",
- TargetURL: "http://10.0.0.10:8080/app1",
- Protocol: "both",
- }
- payload, _ := json.Marshal(newRule)
- req = httptest.NewRequest(http.MethodPost, "/api/proxy/rules", bytes.NewReader(payload))
- rec = httptest.NewRecorder()
- srv.mux.ServeHTTP(rec, req)
- if rec.Code != http.StatusOK {
- t.Fatalf("POST /api/proxy/rules status = %d; want 200, body: %s", rec.Code, rec.Body.String())
- }
- var created reverseproxy.Rule
- if err := json.NewDecoder(rec.Body).Decode(&created); err != nil {
- t.Fatalf("failed to decode created rule: %v", err)
- }
- if created.ID == "" || created.Name != "Web App" {
- t.Errorf("unexpected created rule: %+v", created)
- }
- // 3. GET /api/proxy/rules
- req = httptest.NewRequest(http.MethodGet, "/api/proxy/rules", nil)
- rec = httptest.NewRecorder()
- srv.mux.ServeHTTP(rec, req)
- if rec.Code != http.StatusOK {
- t.Fatalf("GET /api/proxy/rules status = %d", rec.Code)
- }
- var rules []*reverseproxy.Rule
- _ = json.NewDecoder(rec.Body).Decode(&rules)
- if len(rules) != 1 {
- t.Errorf("expected 1 rule, got %d", len(rules))
- }
- // 4. POST /api/proxy/rules/{id}/state (Toggle state)
- statePayload := bytes.NewReader([]byte(`{"enabled":false}`))
- req = httptest.NewRequest(http.MethodPost, "/api/proxy/rules/"+created.ID+"/state", statePayload)
- rec = httptest.NewRecorder()
- srv.mux.ServeHTTP(rec, req)
- if rec.Code != http.StatusOK {
- t.Fatalf("POST /api/proxy/rules/{id}/state status = %d", rec.Code)
- }
- // 5. GET /api/proxy/status
- req = httptest.NewRequest(http.MethodGet, "/api/proxy/status", nil)
- rec = httptest.NewRecorder()
- srv.mux.ServeHTTP(rec, req)
- if rec.Code != http.StatusOK {
- t.Fatalf("GET /api/proxy/status status = %d", rec.Code)
- }
- var status map[string]any
- _ = json.NewDecoder(rec.Body).Decode(&status)
- if status["rules_count"].(float64) != 1 {
- t.Errorf("expected rules_count 1, got %v", status["rules_count"])
- }
- // 6. DELETE /api/proxy/rules/{id}
- req = httptest.NewRequest(http.MethodDelete, "/api/proxy/rules/"+created.ID, nil)
- rec = httptest.NewRecorder()
- srv.mux.ServeHTTP(rec, req)
- if rec.Code != http.StatusOK {
- t.Fatalf("DELETE /api/proxy/rules/{id} status = %d", rec.Code)
- }
- }
|