snapshot of https://github.com/centrifugal/centrifugo.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
test / Lint (push) Failing after 3s
test / Test with Go 1.26.8 (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-16 01:17:21 +05:00
commit b352a9a30d
472 changed files with 108375 additions and 0 deletions

46
internal/origin/origin.go Normal file
View File

@@ -0,0 +1,46 @@
package origin
import (
"fmt"
"net/http"
"strings"
"github.com/gobwas/glob"
)
type PatternChecker struct {
allowedOrigins []*glob.Pattern
}
func NewPatternChecker(allowedOrigins []string) (*PatternChecker, error) {
var globs []*glob.Pattern
for _, pattern := range allowedOrigins {
// Origin is matched in lower case (scheme and host are case-insensitive),
// so patterns must be lower-cased too – otherwise a pattern containing
// upper-case letters could never match.
g, err := glob.Compile(strings.ToLower(pattern))
if err != nil {
return nil, fmt.Errorf("malformed origin pattern: %w", err)
}
globs = append(globs, g)
}
return &PatternChecker{
allowedOrigins: globs,
}, nil
}
func (a *PatternChecker) Check(r *http.Request) bool {
origin := r.Header.Get("Origin")
if origin == "" {
return true
}
origin = strings.ToLower(origin)
for _, pattern := range a.allowedOrigins {
if pattern.Match(origin) {
return true
}
}
return false
}

View File

@@ -0,0 +1,114 @@
package origin
import (
"net/http/httptest"
"testing"
"github.com/stretchr/testify/require"
)
func TestPatternCheck(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
origin string
originPatterns []string
success bool
}{
{
name: "empty_origin",
origin: "",
originPatterns: []string{
"*.example.com",
},
success: true,
},
{
name: "origin_patterns_match",
origin: "https://two.Example.com",
originPatterns: []string{
"*.example.com",
"foo.com",
},
success: true,
},
{
name: "origin_patterns_no_match",
origin: "https://two.Example.com",
originPatterns: []string{
"foo.com",
"bar.com",
},
success: false,
},
{
name: "origin_patterns_uppercase_in_pattern",
origin: "https://two.example.com",
originPatterns: []string{
"https://*.Example.com",
},
success: true,
},
{
name: "origin_patterns_uppercase_in_pattern_and_origin",
origin: "HTTPS://App.Example.com",
originPatterns: []string{
"https://APP.example.COM",
},
success: true,
},
{
name: "origin_patterns_uppercase_in_pattern_no_match",
origin: "https://two.example.org",
originPatterns: []string{
"https://*.Example.com",
},
success: false,
},
{
name: "origin_patterns_cyrillic_e_in_origin",
origin: "https://two.еxample.com",
originPatterns: []string{
"*.example.com",
"foo.com",
},
success: false,
},
{
name: "file_origin",
origin: "file://",
originPatterns: []string{
"file://*",
},
success: true,
},
{
name: "null_origin",
origin: "null",
originPatterns: []string{
"null",
},
success: true,
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
r := httptest.NewRequest("GET", "https://example.com/websocket/connection", nil)
r.Header.Set("Origin", tc.origin)
a, err := NewPatternChecker(tc.originPatterns)
require.NoError(t, err)
ok := a.Check(r)
if tc.success {
require.True(t, ok)
} else {
require.False(t, ok)
}
})
}
}