Skip to content

Commit 92b3e4e

Browse files
committed
Introduce wrapper middleware to intercept http requests
1 parent e6b1903 commit 92b3e4e

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

pkg/kubernetes-mcp-server/cmd/root.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"strconv"
1010
"strings"
1111

12+
"github.com/manusa/kubernetes-mcp-server/pkg/middleware"
13+
1214
"github.com/spf13/cobra"
1315

1416
"k8s.io/cli-runtime/pkg/genericiooptions"
@@ -206,9 +208,11 @@ func (m *MCPServerOptions) Run() error {
206208

207209
if m.StaticConfig.Port != "" {
208210
mux := http.NewServeMux()
211+
wrappedMux := middleware.RequestMiddleware(mux)
212+
209213
httpServer := &http.Server{
210214
Addr: ":" + m.StaticConfig.Port,
211-
Handler: mux,
215+
Handler: wrappedMux,
212216
}
213217

214218
sseServer := mcpServer.ServeSse(m.SSEBaseUrl, httpServer)

pkg/mcp/mcp.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ func (s *Server) ServeHTTP(httpServer *http.Server) *server.StreamableHTTPServer
9898
options := []server.StreamableHTTPOption{
9999
server.WithHTTPContextFunc(contextFunc),
100100
server.WithStreamableHTTPServer(httpServer),
101+
server.WithStateLess(true),
101102
}
102103
return server.NewStreamableHTTPServer(s.server, options...)
103104
}

pkg/middleware/middleware.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package middleware
2+
3+
import (
4+
"bufio"
5+
"net"
6+
"net/http"
7+
"time"
8+
9+
"k8s.io/klog/v2"
10+
)
11+
12+
func RequestMiddleware(next http.Handler) http.Handler {
13+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
14+
start := time.Now()
15+
16+
lrw := &loggingResponseWriter{
17+
ResponseWriter: w,
18+
statusCode: http.StatusOK,
19+
}
20+
21+
next.ServeHTTP(lrw, r)
22+
23+
duration := time.Since(start)
24+
klog.V(5).Infof("%s %s %d %v", r.Method, r.URL.Path, lrw.statusCode, duration)
25+
})
26+
}
27+
28+
type loggingResponseWriter struct {
29+
http.ResponseWriter
30+
statusCode int
31+
headerWritten bool
32+
}
33+
34+
func (lrw *loggingResponseWriter) WriteHeader(code int) {
35+
if !lrw.headerWritten {
36+
lrw.statusCode = code
37+
lrw.headerWritten = true
38+
lrw.ResponseWriter.WriteHeader(code)
39+
}
40+
}
41+
42+
func (lrw *loggingResponseWriter) Write(b []byte) (int, error) {
43+
if !lrw.headerWritten {
44+
lrw.statusCode = http.StatusOK
45+
lrw.headerWritten = true
46+
}
47+
return lrw.ResponseWriter.Write(b)
48+
}
49+
50+
func (lrw *loggingResponseWriter) Flush() {
51+
if flusher, ok := lrw.ResponseWriter.(http.Flusher); ok {
52+
flusher.Flush()
53+
}
54+
}
55+
56+
func (lrw *loggingResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
57+
if hijacker, ok := lrw.ResponseWriter.(http.Hijacker); ok {
58+
return hijacker.Hijack()
59+
}
60+
return nil, nil, http.ErrNotSupported
61+
}

0 commit comments

Comments
 (0)