• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nagayon-935 / Conduit / 23598239365

26 Mar 2026 01:57PM UTC coverage: 60.314% (+0.3%) from 60.0%
23598239365

push

github

nagayon-935
refactor: extract token size constant

538 of 892 relevant lines covered (60.31%)

7.47 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.36
/internal/api/handler.go
1
package api
2

3
import (
4
        "encoding/json"
5
        "log/slog"
6
        "net/http"
7

8
        "github.com/gorilla/websocket"
9
        "github.com/nagayon-935/conduit/internal/config"
10
        "github.com/nagayon-935/conduit/internal/connlog"
11
        "github.com/nagayon-935/conduit/internal/session"
12
        "github.com/nagayon-935/conduit/internal/sshconn"
13
        "github.com/nagayon-935/conduit/internal/vault"
14
)
15

16
const (
17
        contentTypeJSON    = "application/json"
18
        wsReadBufferSize   = 4096
19
        wsWriteBufferSize  = 4096
20
)
21

22
// Handler is the root HTTP handler for the Conduit API.
23
type Handler struct {
24
        config   *config.Config
25
        sessions *session.Manager
26
        vault    vault.VaultClient
27
        dialer   sshconn.SSHDialer
28
        upgrader websocket.Upgrader
29
        logs     *connlog.Store
30
}
31

32
// NewHandler constructs a Handler wiring together all application dependencies.
33
func NewHandler(cfg *config.Config, sm *session.Manager, vc vault.VaultClient, d sshconn.SSHDialer, ls *connlog.Store) *Handler {
14✔
34
        return &Handler{
14✔
35
                config:   cfg,
14✔
36
                sessions: sm,
14✔
37
                vault:    vc,
14✔
38
                dialer:   d,
14✔
39
                logs:     ls,
14✔
40
                upgrader: websocket.Upgrader{
14✔
41
                        // Allow all origins for development; tighten for production.
14✔
42
                        CheckOrigin:     func(r *http.Request) bool { return true },
15✔
43
                        ReadBufferSize:  wsReadBufferSize,
44
                        WriteBufferSize: wsWriteBufferSize,
45
                },
46
        }
47
}
48

49
// Routes registers all API routes and returns the root http.Handler.
50
func (h *Handler) Routes() http.Handler {
14✔
51
        mux := http.NewServeMux()
14✔
52
        mux.HandleFunc("POST /api/connect", h.handleConnect)
14✔
53
        mux.HandleFunc("GET /ws", h.handleTerminal)
14✔
54
        mux.HandleFunc("GET /healthz", h.handleHealth)
14✔
55
        mux.HandleFunc("GET /api/sessions", h.handleListSessions)
14✔
56
        mux.HandleFunc("DELETE /api/sessions/{token}", h.handleKillSession)
14✔
57
        mux.HandleFunc("GET /api/logs", h.handleListLogs)
14✔
58
        return corsMiddleware(loggingMiddleware(mux))
14✔
59
}
14✔
60

61
// handleHealth is a simple liveness probe.
62
func (h *Handler) handleHealth(w http.ResponseWriter, r *http.Request) {
2✔
63
        w.Header().Set("Content-Type", contentTypeJSON)
2✔
64
        w.WriteHeader(http.StatusOK)
2✔
65
        _, _ = w.Write([]byte(`{"status":"ok"}`))
2✔
66
}
2✔
67

68
// apiError writes a structured JSON error response.
69
func apiError(w http.ResponseWriter, code int, message, errCode string) {
8✔
70
        w.Header().Set("Content-Type", contentTypeJSON)
8✔
71
        w.WriteHeader(code)
8✔
72
        body, _ := json.Marshal(map[string]string{
8✔
73
                "error": message,
8✔
74
                "code":  errCode,
8✔
75
        })
8✔
76
        _, _ = w.Write(body)
8✔
77
}
8✔
78

79
// writeJSON marshals v and writes it as a JSON response.
80
func writeJSON(w http.ResponseWriter, code int, v any) {
1✔
81
        w.Header().Set("Content-Type", contentTypeJSON)
1✔
82
        w.WriteHeader(code)
1✔
83
        if err := json.NewEncoder(w).Encode(v); err != nil {
1✔
84
                slog.Error("writeJSON: encode failed", "error", err)
×
85
        }
×
86
}
87

88
// corsMiddleware adds permissive CORS headers (suitable for development).
89
func corsMiddleware(next http.Handler) http.Handler {
14✔
90
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
28✔
91
                w.Header().Set("Access-Control-Allow-Origin", "*")
14✔
92
                w.Header().Set("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS")
14✔
93
                w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
14✔
94
                if r.Method == http.MethodOptions {
15✔
95
                        w.WriteHeader(http.StatusNoContent)
1✔
96
                        return
1✔
97
                }
1✔
98
                next.ServeHTTP(w, r)
13✔
99
        })
100
}
101

102
// loggingMiddleware logs each incoming HTTP request.
103
func loggingMiddleware(next http.Handler) http.Handler {
14✔
104
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
27✔
105
                slog.Info("http request", "method", r.Method, "path", r.URL.Path, "remote_addr", r.RemoteAddr)
13✔
106
                next.ServeHTTP(w, r)
13✔
107
        })
13✔
108
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc