123 lines
3.4 KiB
Go
123 lines
3.4 KiB
Go
package surf
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"git.golem15.com/golem15/summercms/backpack"
|
|
"git.golem15.com/golem15/summercms/compass"
|
|
"git.golem15.com/golem15/summercms/party"
|
|
)
|
|
|
|
func TestCORSLaravelGlobMatchesNestedPaths(t *testing.T) {
|
|
re := compileLaravelGlob("api/*")
|
|
if re == nil || !re.MatchString("api/v1/fonoteka/genres") {
|
|
t.Fatal("api/* must match api/v1/fonoteka/genres (Laravel Str::is, not Go path.Match)")
|
|
}
|
|
if re.MatchString("_fonoteka/api/v1/genres") {
|
|
t.Fatal("api/* must not match _fonoteka/api/v1/genres")
|
|
}
|
|
mcp := compileLaravelGlob("oauth/mcp/*")
|
|
if mcp == nil || !mcp.MatchString("oauth/mcp/token") {
|
|
t.Fatal("oauth/mcp/* must match oauth/mcp/token")
|
|
}
|
|
}
|
|
|
|
func TestCORSPathScopedHeaders(t *testing.T) {
|
|
cfg := CORSConfig{
|
|
Paths: []string{"api/*", "oauth/mcp/*"},
|
|
AllowedMethods: []string{"*"},
|
|
AllowedOrigins: []string{"*"},
|
|
AllowedHeaders: []string{"*"},
|
|
}
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("GET /api/v1/fonoteka/genres", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
})
|
|
mux.HandleFunc("GET /_fonoteka/api/v1/genres", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
})
|
|
h := pathScopedCORS(cfg, mux)
|
|
|
|
rec := httptest.NewRecorder()
|
|
h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/v1/fonoteka/genres", nil))
|
|
if rec.Header().Get("Access-Control-Allow-Origin") != "*" {
|
|
t.Fatalf("token group ACAO = %q", rec.Header().Get("Access-Control-Allow-Origin"))
|
|
}
|
|
|
|
rec = httptest.NewRecorder()
|
|
h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/_fonoteka/api/v1/genres", nil))
|
|
if got := rec.Header().Get("Access-Control-Allow-Origin"); got != "" {
|
|
t.Fatalf("JWT group ACAO = %q, want empty", got)
|
|
}
|
|
}
|
|
|
|
func TestCORSConfigLoadedFromHTTPSection(t *testing.T) {
|
|
cfg := writeHTTPConfig(t, `
|
|
cors:
|
|
paths: ["api/*"]
|
|
allowed_methods: ["*"]
|
|
allowed_origins: ["*"]
|
|
allowed_origins_patterns: []
|
|
allowed_headers: ["*"]
|
|
exposed_headers: []
|
|
max_age: 0
|
|
supports_credentials: false
|
|
`)
|
|
got, err := LoadCORSConfig(cfg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(got.Paths) != 1 || got.Paths[0] != "api/*" {
|
|
t.Fatalf("paths = %v", got.Paths)
|
|
}
|
|
if !containsStar(got.AllowedOrigins) {
|
|
t.Fatalf("origins = %v", got.AllowedOrigins)
|
|
}
|
|
}
|
|
|
|
func writeHTTPConfig(t *testing.T, httpYAML string) *compass.Config {
|
|
t.Helper()
|
|
dir := t.TempDir()
|
|
if err := os.WriteFile(filepath.Join(dir, "app.yaml"), []byte("name: cors-test\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(dir, "http.yaml"), []byte(httpYAML), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cfg, err := compass.Open(compass.Options{
|
|
Dir: dir,
|
|
Environ: []string{"SUMMER_ENV=development"},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
func TestCORSAssembleUsesConfig(t *testing.T) {
|
|
cfg := writeHTTPConfig(t, `
|
|
body_limits:
|
|
default_bytes: 1048576
|
|
upload_bytes: 1048576
|
|
cors:
|
|
paths: ["api/*"]
|
|
allowed_methods: ["*"]
|
|
allowed_origins: ["*"]
|
|
allowed_headers: ["*"]
|
|
`)
|
|
p := assemblePlugin{id: "golem15.demo", path: "/genres"}
|
|
h, err := Assemble(backpack.New(cfg), []party.Plugin{p})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
rec := httptest.NewRecorder()
|
|
h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/genres", nil))
|
|
if rec.Header().Get("Access-Control-Allow-Origin") != "*" {
|
|
t.Fatalf("ACAO = %q", rec.Header().Get("Access-Control-Allow-Origin"))
|
|
}
|
|
}
|