mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-20 11:21:49 +00:00
fix: cors
This commit is contained in:
+48
-2
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -106,10 +107,55 @@ func (gw *GatewayConfig) SetupRoutes() http.Handler {
|
||||
return r
|
||||
}
|
||||
|
||||
// corsMiddleware adds CORS headers for browser requests from the dev UI.
|
||||
// corsAllowedOrigins builds the set of allowed CORS origins from localhost and
|
||||
// all local non-loopback IPs on the hive-ui port (default 3000). This allows
|
||||
// the UI to be accessed from any local address, not just localhost.
|
||||
func corsAllowedOrigins() map[string]struct{} {
|
||||
origins := map[string]struct{}{
|
||||
"https://localhost:3000": {},
|
||||
}
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return origins
|
||||
}
|
||||
for _, iface := range ifaces {
|
||||
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
|
||||
continue
|
||||
}
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
var ip net.IP
|
||||
switch v := addr.(type) {
|
||||
case *net.IPNet:
|
||||
ip = v.IP
|
||||
case *net.IPAddr:
|
||||
ip = v.IP
|
||||
}
|
||||
if ip == nil || ip.IsLoopback() || ip.To4() == nil {
|
||||
continue
|
||||
}
|
||||
origins[fmt.Sprintf("https://%s:3000", ip.String())] = struct{}{}
|
||||
}
|
||||
}
|
||||
return origins
|
||||
}
|
||||
|
||||
// corsMiddleware adds CORS headers for browser requests from the hive-ui.
|
||||
func corsMiddleware(next http.Handler) http.Handler {
|
||||
allowed := corsAllowedOrigins()
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "https://localhost:3000")
|
||||
origin := r.Header.Get("Origin")
|
||||
if origin == "" {
|
||||
origin = "https://localhost:3000"
|
||||
}
|
||||
if _, ok := allowed[origin]; ok {
|
||||
w.Header().Set("Access-Control-Allow-Origin", origin)
|
||||
} else {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "https://localhost:3000")
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,HEAD,OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "*")
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
|
||||
@@ -860,6 +860,43 @@ func TestCorsMiddleware_OPTIONSRequest(t *testing.T) {
|
||||
assert.Equal(t, "https://localhost:3000", w.Header().Get("Access-Control-Allow-Origin"))
|
||||
}
|
||||
|
||||
func TestCorsMiddleware_LocalIPOrigin(t *testing.T) {
|
||||
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
})
|
||||
|
||||
handler := corsMiddleware(next)
|
||||
|
||||
// Request from a local IP should be reflected
|
||||
allowed := corsAllowedOrigins()
|
||||
for origin := range allowed {
|
||||
if origin == "https://localhost:3000" {
|
||||
continue
|
||||
}
|
||||
req := httptest.NewRequest("GET", "/", nil)
|
||||
req.Header.Set("Origin", origin)
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
assert.Equal(t, origin, w.Header().Get("Access-Control-Allow-Origin"))
|
||||
return // test one IP is enough
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorsMiddleware_UnknownOrigin(t *testing.T) {
|
||||
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
})
|
||||
|
||||
handler := corsMiddleware(next)
|
||||
req := httptest.NewRequest("GET", "/", nil)
|
||||
req.Header.Set("Origin", "https://evil.example.com")
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
|
||||
// Unknown origins fall back to localhost
|
||||
assert.Equal(t, "https://localhost:3000", w.Header().Get("Access-Control-Allow-Origin"))
|
||||
}
|
||||
|
||||
func TestSlogRequestLogger_CallsNext(t *testing.T) {
|
||||
nextCalled := false
|
||||
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Reference in New Issue
Block a user