Repository navigation
Expand file tree
/
Copy pathinit_test.go
More file actions
134 lines (104 loc) · 4.29 KB
/
Copy pathinit_test.go
File metadata and controls
134 lines (104 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package headers
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/roadrunner-server/errors"
"github.com/stretchr/testify/require"
)
// stubConfigurer hands Init a pre-built Config instead of decoding YAML, so the
// tests exercise the plugin's own option mapping rather than the config decoder.
type stubConfigurer struct {
sections map[string]bool
cfg *Config
}
func (s *stubConfigurer) Has(name string) bool { return s.sections[name] }
func (s *stubConfigurer) UnmarshalKey(_ string, out any) error {
p, ok := out.(**Config)
if !ok {
return errors.Str("unexpected target type")
}
*p = s.cfg
return nil
}
func bothSections() map[string]bool {
return map[string]bool{RootPluginName: true, configKey: true}
}
func TestInitDisabledWithoutHTTPSection(t *testing.T) {
err := (&Plugin{}).Init(&stubConfigurer{sections: map[string]bool{}})
require.Error(t, err)
require.True(t, errors.Is(errors.Disabled, err))
}
func TestInitDisabledWithoutHeadersSection(t *testing.T) {
err := (&Plugin{}).Init(&stubConfigurer{sections: map[string]bool{RootPluginName: true}})
require.Error(t, err)
require.True(t, errors.Is(errors.Disabled, err))
}
func TestInitWithoutCORSLeavesHandlerUnset(t *testing.T) {
p := &Plugin{}
require.NoError(t, p.Init(&stubConfigurer{sections: bothSections(), cfg: &Config{}}))
require.Nil(t, p.cors)
require.Nil(t, p.allowedOriginRegex)
require.NotNil(t, p.prop)
}
func TestInitCompilesAllowedOriginRegex(t *testing.T) {
p := &Plugin{}
cfg := &Config{CORS: &CORSConfig{AllowedOriginRegex: `^https?://example\.com$`}}
require.NoError(t, p.Init(&stubConfigurer{sections: bothSections(), cfg: cfg}))
require.NotNil(t, p.allowedOriginRegex)
require.True(t, p.allowedOriginRegex.MatchString("https://example.com"))
require.False(t, p.allowedOriginRegex.MatchString("https://evil.com"))
}
func TestInitRejectsBadAllowedOriginRegex(t *testing.T) {
cfg := &Config{CORS: &CORSConfig{AllowedOriginRegex: "("}}
err := (&Plugin{}).Init(&stubConfigurer{sections: bothSections(), cfg: cfg})
require.Error(t, err)
}
// TestInitDefaultsOptionsSuccessStatus covers the compatibility default: an
// unset options_success_status must still answer preflights with 200.
func TestInitDefaultsOptionsSuccessStatus(t *testing.T) {
p := &Plugin{}
cfg := &Config{CORS: &CORSConfig{AllowedOrigin: "*", AllowedMethods: "GET"}}
require.NoError(t, p.Init(&stubConfigurer{sections: bothSections(), cfg: cfg}))
rec := httptest.NewRecorder()
req := httptest.NewRequestWithContext(t.Context(), http.MethodOptions, "/", nil)
req.Header.Set("Origin", "http://example.com")
req.Header.Set("Access-Control-Request-Method", http.MethodGet)
p.Middleware(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})).ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Result().StatusCode)
}
func TestInitHonoursCustomOptionsSuccessStatus(t *testing.T) {
p := &Plugin{}
cfg := &Config{CORS: &CORSConfig{
AllowedOrigin: "*",
AllowedMethods: "GET",
OptionsSuccessStatus: http.StatusNoContent,
}}
require.NoError(t, p.Init(&stubConfigurer{sections: bothSections(), cfg: cfg}))
rec := httptest.NewRecorder()
req := httptest.NewRequestWithContext(t.Context(), http.MethodOptions, "/", nil)
req.Header.Set("Origin", "http://example.com")
req.Header.Set("Access-Control-Request-Method", http.MethodGet)
p.Middleware(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})).ServeHTTP(rec, req)
require.Equal(t, http.StatusNoContent, rec.Result().StatusCode)
}
// TestMiddlewareAppliesConfiguredHeaders checks both directions in one pass: the
// request header must be visible to the downstream handler, the response header
// must reach the recorder.
func TestMiddlewareAppliesConfiguredHeaders(t *testing.T) {
p := &Plugin{cfg: &Config{
Request: map[string]string{"Input": "custom-header"},
Response: map[string]string{"Output": "output-header"},
}}
var seen string
h := p.Middleware(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
seen = r.Header.Get("Input")
}))
rec := httptest.NewRecorder()
h.ServeHTTP(rec, httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/", nil))
require.Equal(t, "custom-header", seen)
require.Equal(t, "output-header", rec.Header().Get("Output"))
}
func TestName(t *testing.T) {
require.Equal(t, PluginName, (&Plugin{}).Name())
}