Skip to content

Commit 39e5729

Browse files
authored
fix: add showing html response also if auth is disabled (#61)
1 parent d171699 commit 39e5729

File tree

3 files changed

+49
-30
lines changed

3 files changed

+49
-30
lines changed

cmd/serve.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/go-chi/cors"
1414
"github.com/go-logr/stdr"
1515
"github.com/hyprmcp/mcp-gateway/config"
16+
"github.com/hyprmcp/mcp-gateway/htmlresponse"
1617
"github.com/hyprmcp/mcp-gateway/log"
1718
"github.com/hyprmcp/mcp-gateway/oauth"
1819
"github.com/hyprmcp/mcp-gateway/proxy"
@@ -107,6 +108,7 @@ func runServe(ctx context.Context, opts ServeOptions) error {
107108
func newRouter(ctx context.Context, config *config.Config) (http.Handler, error) {
108109
mux := http.NewServeMux()
109110

111+
htmlHandler := htmlresponse.NewHandler(config, false)
110112
oauthManager, err := oauth.NewManager(ctx, config)
111113
if err != nil {
112114
return nil, err
@@ -119,6 +121,7 @@ func newRouter(ctx context.Context, config *config.Config) (http.Handler, error)
119121
for _, proxyConfig := range config.Proxy {
120122
if proxyConfig.Http != nil && proxyConfig.Http.Url != nil {
121123
handler := proxy.NewProxyHandler(&proxyConfig)
124+
handler = htmlHandler.Handler(handler)
122125

123126
if proxyConfig.Authentication.Enabled {
124127
handler = oauthManager.Handler(handler)

htmlresponse/handle.go

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ var (
1717
tpl *template.Template
1818
)
1919

20+
const (
21+
ContentTypeTextHTML = "text/html"
22+
)
23+
2024
func init() {
2125
if t, err := template.New("").Parse(ts); err != nil {
2226
panic(err)
@@ -26,14 +30,28 @@ func init() {
2630
}
2731

2832
type handler struct {
29-
config *config.Config
33+
config *config.Config
34+
alwaysCallNext bool
35+
}
36+
37+
func NewHandler(config *config.Config, alwaysCallNext bool) *handler {
38+
return &handler{config: config, alwaysCallNext: alwaysCallNext}
3039
}
3140

32-
func NewHandler(config *config.Config) *handler {
33-
return &handler{config: config}
41+
func (h *handler) Handler(next http.Handler) http.Handler {
42+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
43+
isAcceptHTML := strings.Contains(r.Header.Get("Accept"), ContentTypeTextHTML)
44+
if h.alwaysCallNext || !isAcceptHTML {
45+
next.ServeHTTP(w, r)
46+
}
47+
48+
if isAcceptHTML {
49+
h.handleHtml(w, r)
50+
}
51+
})
3452
}
3553

36-
func (h *handler) Handle(w http.ResponseWriter, r *http.Request) error {
54+
func (h *handler) handleHtml(w http.ResponseWriter, r *http.Request) {
3755
var data struct {
3856
Name string
3957
Url string
@@ -49,5 +67,11 @@ func (h *handler) Handle(w http.ResponseWriter, r *http.Request) error {
4967
data.Name = ps[nameIdx]
5068
}
5169

52-
return tpl.Execute(w, data)
70+
w.Header().Set("Content-Type", ContentTypeTextHTML)
71+
72+
if !h.alwaysCallNext {
73+
w.WriteHeader(http.StatusNotAcceptable)
74+
}
75+
76+
_ = tpl.Execute(w, data)
5377
}

oauth/oauth.go

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -85,35 +85,27 @@ func (mgr *Manager) Register(mux *http.ServeMux) error {
8585
}
8686

8787
func (mgr *Manager) Handler(next http.Handler) http.Handler {
88-
htmlHandler := htmlresponse.NewHandler(mgr.config)
88+
htmlHandler := htmlresponse.NewHandler(mgr.config, true)
8989
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
9090
rawToken :=
9191
strings.TrimSpace(strings.TrimPrefix(strings.TrimSpace(r.Header.Get("Authorization")), "Bearer"))
92-
93-
shouldCallNext := true
94-
95-
token, err := jwt.ParseString(rawToken, jwt.WithKeySet(mgr.jwkSet))
96-
if err != nil {
97-
metadataURL, _ := url.Parse(mgr.config.Host.String())
98-
metadataURL.Path = ProtectedResourcePath
99-
metadataURL = metadataURL.JoinPath(r.URL.Path)
100-
w.Header().Set(
101-
"WWW-Authenticate",
102-
fmt.Sprintf(`Bearer resource_metadata="%s"`, metadataURL.String()),
103-
)
104-
w.WriteHeader(http.StatusUnauthorized)
105-
shouldCallNext = false
106-
}
107-
108-
if strings.Contains(r.Header.Get("Accept"), "text/html") {
109-
if err := htmlHandler.Handle(w, r); err != nil {
110-
log.Get(r.Context()).Error(err, "failed to handle html response")
111-
}
112-
shouldCallNext = false
113-
}
114-
115-
if shouldCallNext {
92+
if token, err := jwt.ParseString(rawToken, jwt.WithKeySet(mgr.jwkSet)); err != nil {
93+
htmlHandler.Handler(mgr.unauthorizedHandler()).ServeHTTP(w, r)
94+
} else {
11695
next.ServeHTTP(w, r.WithContext(TokenContext(r.Context(), token, rawToken)))
11796
}
11897
})
11998
}
99+
100+
func (mgr *Manager) unauthorizedHandler() http.HandlerFunc {
101+
return func(w http.ResponseWriter, r *http.Request) {
102+
metadataURL, _ := url.Parse(mgr.config.Host.String())
103+
metadataURL.Path = ProtectedResourcePath
104+
metadataURL = metadataURL.JoinPath(r.URL.Path)
105+
w.Header().Set(
106+
"WWW-Authenticate",
107+
fmt.Sprintf(`Bearer resource_metadata="%s"`, metadataURL.String()),
108+
)
109+
w.WriteHeader(http.StatusUnauthorized)
110+
}
111+
}

0 commit comments

Comments
 (0)