@marcel91200 / caddy Mirror · read-only / commits / bc00d840
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

Export types and fields necessary to build configs (for config adapters)

Also flag most fields with 'omitempty' for JSON marshaling

Matthew Holt committed May 22, 2019 at 12:32 UTC bc00d840e845d42145954839b88f1e836cd51bfd
11 files changed +133 -131
caddy.go
+2 -2
@@ -136,10 +136,10 @@ type App interface {
136
137 // Config represents a Caddy configuration.
138 type Config struct {
139 - StorageRaw json.RawMessage `json:"storage"`
139 + StorageRaw json.RawMessage `json:"storage,omitempty"`
140 storage certmagic.Storage
141
142 - AppsRaw map[string]json.RawMessage `json:"apps"`
142 + AppsRaw map[string]json.RawMessage `json:"apps,omitempty"`
143
144 // apps stores the decoded Apps values,
145 // keyed by module name.
modules/caddyhttp/caddyhttp.go
+7 -7
@@ -32,10 +32,10 @@ func init() {
32
33 // App is the HTTP app for Caddy.
34 type App struct {
35 - HTTPPort int `json:"http_port"`
36 - HTTPSPort int `json:"https_port"`
37 - GracePeriod caddy2.Duration `json:"grace_period"`
38 - Servers map[string]*Server `json:"servers"`
35 + HTTPPort int `json:"http_port,omitempty"`
36 + HTTPSPort int `json:"https_port,omitempty"`
37 + GracePeriod caddy2.Duration `json:"grace_period,omitempty"`
38 + Servers map[string]*Server `json:"servers,omitempty"`
39
40 servers []*http.Server
41
@@ -188,7 +188,7 @@ func (app *App) automaticHTTPS() error {
188 domainSet := make(map[string]struct{})
189 for _, route := range srv.Routes {
190 for _, m := range route.matchers {
191 - if hm, ok := m.(*matchHost); ok {
191 + if hm, ok := m.(*MatchHost); ok {
192 for _, d := range *hm {
193 if !certmagic.HostQualifies(d) {
194 continue
@@ -246,8 +246,8 @@ func (app *App) automaticHTTPS() error {
246
247 redirRoutes = append(redirRoutes, ServerRoute{
248 matchers: []RequestMatcher{
249 - matchProtocol("http"),
250 - matchHost(domains),
249 + MatchProtocol("http"),
250 + MatchHost(domains),
251 },
252 responder: Static{
253 StatusCode: http.StatusTemporaryRedirect, // TODO: use permanent redirect instead
modules/caddyhttp/fileserver/browse.go
+1 -1
@@ -15,7 +15,7 @@ import (
15
16 // Browse configures directory browsing.
17 type Browse struct {
18 - TemplateFile string `json:"template_file"`
18 + TemplateFile string `json:"template_file,omitempty"`
19
20 template *template.Template
21 }
modules/caddyhttp/fileserver/staticfiles.go
+8 -8
@@ -27,14 +27,14 @@ func init() {
27
28 // FileServer implements a static file server responder for Caddy.
29 type FileServer struct {
30 - Root string `json:"root"` // default is current directory
31 - Hide []string `json:"hide"`
32 - IndexNames []string `json:"index_names"`
33 - Files []string `json:"files"` // all relative to the root; default is request URI path
34 - SelectionPolicy string `json:"selection_policy"`
35 - Rehandle bool `json:"rehandle"` // issue a rehandle (internal redirect) if request is rewritten
36 - Fallback caddyhttp.RouteList `json:"fallback"`
37 - Browse *Browse `json:"browse"`
30 + Root string `json:"root,omitempty"` // default is current directory
31 + Hide []string `json:"hide,omitempty"`
32 + IndexNames []string `json:"index_names,omitempty"`
33 + Files []string `json:"files,omitempty"` // all relative to the root; default is request URI path
34 + SelectionPolicy string `json:"selection_policy,omitempty"`
35 + Rehandle bool `json:"rehandle,omitempty"` // issue a rehandle (internal redirect) if request is rewritten
36 + Fallback caddyhttp.RouteList `json:"fallback,omitempty"`
37 + Browse *Browse `json:"browse,omitempty"`
38 // TODO: Etag
39 // TODO: Content negotiation
40 }
modules/caddyhttp/headers/headers.go
+8 -8
@@ -17,22 +17,22 @@ func init() {
17
18 // Headers is a middleware which can mutate HTTP headers.
19 type Headers struct {
20 - Request HeaderOps `json:"request"`
21 - Response RespHeaderOps `json:"response"`
20 + Request *HeaderOps `json:"request,omitempty"`
21 + Response *RespHeaderOps `json:"response,omitempty"`
22 }
23
24 // HeaderOps defines some operations to
25 // perform on HTTP headers.
26 type HeaderOps struct {
27 - Add http.Header `json:"add"`
28 - Set http.Header `json:"set"`
29 - Delete []string `json:"delete"`
27 + Add http.Header `json:"add,omitempty"`
28 + Set http.Header `json:"set,omitempty"`
29 + Delete []string `json:"delete,omitempty"`
30 }
31
32 // RespHeaderOps is like HeaderOps, but
33 // optionally deferred until response time.
34 type RespHeaderOps struct {
35 - HeaderOps
35 + *HeaderOps
36 Deferred bool `json:"deferred"`
37 }
38
@@ -51,7 +51,7 @@ func (h Headers) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhtt
51 return next.ServeHTTP(w, r)
52 }
53
54 -func apply(ops HeaderOps, hdr http.Header, repl caddy2.Replacer) {
54 +func apply(ops *HeaderOps, hdr http.Header, repl caddy2.Replacer) {
55 for fieldName, vals := range ops.Add {
56 fieldName = repl.ReplaceAll(fieldName, "")
57 for _, v := range vals {
@@ -75,7 +75,7 @@ func apply(ops HeaderOps, hdr http.Header, repl caddy2.Replacer) {
75 type responseWriterWrapper struct {
76 *caddyhttp.ResponseWriterWrapper
77 replacer caddy2.Replacer
78 - headerOps HeaderOps
78 + headerOps *HeaderOps
79 wroteHeader bool
80 }
81
modules/caddyhttp/matchers.go
+39 -39
@@ -17,58 +17,58 @@ import (
17 )
18
19 type (
20 - matchHost []string
21 - matchPath []string
22 - matchPathRE struct{ matchRegexp }
23 - matchMethod []string
24 - matchQuery url.Values
25 - matchHeader http.Header
26 - matchHeaderRE map[string]*matchRegexp
27 - matchProtocol string
28 - matchStarlarkExpr string
29 - matchTable string // TODO: finish implementing
20 + MatchHost []string
21 + MatchPath []string
22 + MatchPathRE struct{ matchRegexp }
23 + MatchMethod []string
24 + MatchQuery url.Values
25 + MatchHeader http.Header
26 + MatchHeaderRE map[string]*matchRegexp
27 + MatchProtocol string
28 + MatchStarlarkExpr string
29 + MatchTable string // TODO: finish implementing
30 )
31
32 func init() {
33 caddy2.RegisterModule(caddy2.Module{
34 Name: "http.matchers.host",
35 - New: func() interface{} { return matchHost{} },
35 + New: func() interface{} { return MatchHost{} },
36 })
37 caddy2.RegisterModule(caddy2.Module{
38 Name: "http.matchers.path",
39 - New: func() interface{} { return matchPath{} },
39 + New: func() interface{} { return MatchPath{} },
40 })
41 caddy2.RegisterModule(caddy2.Module{
42 Name: "http.matchers.path_regexp",
43 - New: func() interface{} { return new(matchPathRE) },
43 + New: func() interface{} { return new(MatchPathRE) },
44 })
45 caddy2.RegisterModule(caddy2.Module{
46 Name: "http.matchers.method",
47 - New: func() interface{} { return matchMethod{} },
47 + New: func() interface{} { return MatchMethod{} },
48 })
49 caddy2.RegisterModule(caddy2.Module{
50 Name: "http.matchers.query",
51 - New: func() interface{} { return matchQuery{} },
51 + New: func() interface{} { return MatchQuery{} },
52 })
53 caddy2.RegisterModule(caddy2.Module{
54 Name: "http.matchers.header",
55 - New: func() interface{} { return matchHeader{} },
55 + New: func() interface{} { return MatchHeader{} },
56 })
57 caddy2.RegisterModule(caddy2.Module{
58 Name: "http.matchers.header_regexp",
59 - New: func() interface{} { return matchHeaderRE{} },
59 + New: func() interface{} { return MatchHeaderRE{} },
60 })
61 caddy2.RegisterModule(caddy2.Module{
62 Name: "http.matchers.protocol",
63 - New: func() interface{} { return new(matchProtocol) },
63 + New: func() interface{} { return new(MatchProtocol) },
64 })
65 caddy2.RegisterModule(caddy2.Module{
66 Name: "http.matchers.starlark_expr",
67 - New: func() interface{} { return new(matchStarlarkExpr) },
67 + New: func() interface{} { return new(MatchStarlarkExpr) },
68 })
69 }
70
71 -func (m matchHost) Match(r *http.Request) bool {
71 +func (m MatchHost) Match(r *http.Request) bool {
72 outer:
73 for _, host := range m {
74 if strings.Contains(host, "*") {
@@ -93,7 +93,7 @@ outer:
93 return false
94 }
95
96 -func (m matchPath) Match(r *http.Request) bool {
96 +func (m MatchPath) Match(r *http.Request) bool {
97 for _, matchPath := range m {
98 compare := r.URL.Path
99 if strings.HasPrefix(matchPath, "*") {
@@ -111,12 +111,12 @@ func (m matchPath) Match(r *http.Request) bool {
111 return false
112 }
113
114 -func (m matchPathRE) Match(r *http.Request) bool {
114 +func (m MatchPathRE) Match(r *http.Request) bool {
115 repl := r.Context().Value(caddy2.ReplacerCtxKey).(caddy2.Replacer)
116 return m.match(r.URL.Path, repl, "path_regexp")
117 }
118
119 -func (m matchMethod) Match(r *http.Request) bool {
119 +func (m MatchMethod) Match(r *http.Request) bool {
120 for _, method := range m {
121 if r.Method == method {
122 return true
@@ -125,7 +125,7 @@ func (m matchMethod) Match(r *http.Request) bool {
125 return false
126 }
127
128 -func (m matchQuery) Match(r *http.Request) bool {
128 +func (m MatchQuery) Match(r *http.Request) bool {
129 for param, vals := range m {
130 paramVal := r.URL.Query().Get(param)
131 for _, v := range vals {
@@ -137,7 +137,7 @@ func (m matchQuery) Match(r *http.Request) bool {
137 return false
138 }
139
140 -func (m matchHeader) Match(r *http.Request) bool {
140 +func (m MatchHeader) Match(r *http.Request) bool {
141 for field, allowedFieldVals := range m {
142 var match bool
143 actualFieldVals := r.Header[textproto.CanonicalMIMEHeaderKey(field)]
@@ -157,7 +157,7 @@ func (m matchHeader) Match(r *http.Request) bool {
157 return true
158 }
159
160 -func (m matchHeaderRE) Match(r *http.Request) bool {
160 +func (m MatchHeaderRE) Match(r *http.Request) bool {
161 for field, rm := range m {
162 repl := r.Context().Value(caddy2.ReplacerCtxKey).(caddy2.Replacer)
163 match := rm.match(r.Header.Get(field), repl, "header_regexp")
@@ -168,7 +168,7 @@ func (m matchHeaderRE) Match(r *http.Request) bool {
168 return true
169 }
170
171 -func (m matchHeaderRE) Provision() error {
171 +func (m MatchHeaderRE) Provision() error {
172 for _, rm := range m {
173 err := rm.Provision()
174 if err != nil {
@@ -178,7 +178,7 @@ func (m matchHeaderRE) Provision() error {
178 return nil
179 }
180
181 -func (m matchHeaderRE) Validate() error {
181 +func (m MatchHeaderRE) Validate() error {
182 for _, rm := range m {
183 err := rm.Validate()
184 if err != nil {
@@ -188,7 +188,7 @@ func (m matchHeaderRE) Validate() error {
188 return nil
189 }
190
191 -func (m matchProtocol) Match(r *http.Request) bool {
191 +func (m MatchProtocol) Match(r *http.Request) bool {
192 switch string(m) {
193 case "grpc":
194 return r.Header.Get("content-type") == "application/grpc"
@@ -200,7 +200,7 @@ func (m matchProtocol) Match(r *http.Request) bool {
200 return false
201 }
202
203 -func (m matchStarlarkExpr) Match(r *http.Request) bool {
203 +func (m MatchStarlarkExpr) Match(r *http.Request) bool {
204 input := string(m)
205 thread := new(starlark.Thread)
206 env := caddyscript.MatcherEnv(r)
@@ -264,13 +264,13 @@ var wordRE = regexp.MustCompile(`\w+`)
264
265 // Interface guards
266 var (
267 - _ RequestMatcher = (*matchHost)(nil)
268 - _ RequestMatcher = (*matchPath)(nil)
269 - _ RequestMatcher = (*matchPathRE)(nil)
270 - _ RequestMatcher = (*matchMethod)(nil)
271 - _ RequestMatcher = (*matchQuery)(nil)
272 - _ RequestMatcher = (*matchHeader)(nil)
273 - _ RequestMatcher = (*matchHeaderRE)(nil)
274 - _ RequestMatcher = (*matchProtocol)(nil)
275 - _ RequestMatcher = (*matchStarlarkExpr)(nil)
267 + _ RequestMatcher = (*MatchHost)(nil)
268 + _ RequestMatcher = (*MatchPath)(nil)
269 + _ RequestMatcher = (*MatchPathRE)(nil)
270 + _ RequestMatcher = (*MatchMethod)(nil)
271 + _ RequestMatcher = (*MatchQuery)(nil)
272 + _ RequestMatcher = (*MatchHeader)(nil)
273 + _ RequestMatcher = (*MatchHeaderRE)(nil)
274 + _ RequestMatcher = (*MatchProtocol)(nil)
275 + _ RequestMatcher = (*MatchStarlarkExpr)(nil)
276 )
modules/caddyhttp/matchers_test.go
+48 -48
@@ -13,77 +13,77 @@ import (
13
14 func TestHostMatcher(t *testing.T) {
15 for i, tc := range []struct {
16 - match matchHost
16 + match MatchHost
17 input string
18 expect bool
19 }{
20 {
21 - match: matchHost{},
21 + match: MatchHost{},
22 input: "example.com",
23 expect: false,
24 },
25 {
26 - match: matchHost{"example.com"},
26 + match: MatchHost{"example.com"},
27 input: "example.com",
28 expect: true,
29 },
30 {
31 - match: matchHost{"example.com"},
31 + match: MatchHost{"example.com"},
32 input: "foo.example.com",
33 expect: false,
34 },
35 {
36 - match: matchHost{"example.com"},
36 + match: MatchHost{"example.com"},
37 input: "EXAMPLE.COM",
38 expect: true,
39 },
40 {
41 - match: matchHost{"foo.example.com"},
41 + match: MatchHost{"foo.example.com"},
42 input: "foo.example.com",
43 expect: true,
44 },
45 {
46 - match: matchHost{"foo.example.com"},
46 + match: MatchHost{"foo.example.com"},
47 input: "bar.example.com",
48 expect: false,
49 },
50 {
51 - match: matchHost{"*.example.com"},
51 + match: MatchHost{"*.example.com"},
52 input: "example.com",
53 expect: false,
54 },
55 {
56 - match: matchHost{"*.example.com"},
56 + match: MatchHost{"*.example.com"},
57 input: "foo.example.com",
58 expect: true,
59 },
60 {
61 - match: matchHost{"*.example.com"},
61 + match: MatchHost{"*.example.com"},
62 input: "foo.bar.example.com",
63 expect: false,
64 },
65 {
66 - match: matchHost{"*.example.com", "example.net"},
66 + match: MatchHost{"*.example.com", "example.net"},
67 input: "example.net",
68 expect: true,
69 },
70 {
71 - match: matchHost{"example.net", "*.example.com"},
71 + match: MatchHost{"example.net", "*.example.com"},
72 input: "foo.example.com",
73 expect: true,
74 },
75 {
76 - match: matchHost{"*.example.net", "*.*.example.com"},
76 + match: MatchHost{"*.example.net", "*.*.example.com"},
77 input: "foo.bar.example.com",
78 expect: true,
79 },
80 {
81 - match: matchHost{"*.example.net", "sub.*.example.com"},
81 + match: MatchHost{"*.example.net", "sub.*.example.com"},
82 input: "sub.foo.example.com",
83 expect: true,
84 },
85 {
86 - match: matchHost{"*.example.net", "sub.*.example.com"},
86 + match: MatchHost{"*.example.net", "sub.*.example.com"},
87 input: "sub.foo.example.net",
88 expect: false,
89 },
@@ -99,57 +99,57 @@ func TestHostMatcher(t *testing.T) {
99
100 func TestPathMatcher(t *testing.T) {
101 for i, tc := range []struct {
102 - match matchPath
102 + match MatchPath
103 input string
104 expect bool
105 }{
106 {
107 - match: matchPath{},
107 + match: MatchPath{},
108 input: "/",
109 expect: false,
110 },
111 {
112 - match: matchPath{"/"},
112 + match: MatchPath{"/"},
113 input: "/",
114 expect: true,
115 },
116 {
117 - match: matchPath{"/foo/bar"},
117 + match: MatchPath{"/foo/bar"},
118 input: "/",
119 expect: false,
120 },
121 {
122 - match: matchPath{"/foo/bar"},
122 + match: MatchPath{"/foo/bar"},
123 input: "/foo/bar",
124 expect: true,
125 },
126 {
127 - match: matchPath{"/foo/bar/"},
127 + match: MatchPath{"/foo/bar/"},
128 input: "/foo/bar",
129 expect: false,
130 },
131 {
132 - match: matchPath{"/foo/bar/", "/other"},
132 + match: MatchPath{"/foo/bar/", "/other"},
133 input: "/other/",
134 expect: true,
135 },
136 {
137 - match: matchPath{"*.ext"},
137 + match: MatchPath{"*.ext"},
138 input: "foo.ext",
139 expect: true,
140 },
141 {
142 - match: matchPath{"*.ext"},
142 + match: MatchPath{"*.ext"},
143 input: "/foo/bar.ext",
144 expect: true,
145 },
146 {
147 - match: matchPath{"/foo/*/baz"},
147 + match: MatchPath{"/foo/*/baz"},
148 input: "/foo/bar/baz",
149 expect: true,
150 },
151 {
152 - match: matchPath{"/foo/*/baz/bam"},
152 + match: MatchPath{"/foo/*/baz/bam"},
153 input: "/foo/bar/bam",
154 expect: false,
155 },
@@ -165,49 +165,49 @@ func TestPathMatcher(t *testing.T) {
165
166 func TestPathREMatcher(t *testing.T) {
167 for i, tc := range []struct {
168 - match matchPathRE
168 + match MatchPathRE
169 input string
170 expect bool
171 expectRepl map[string]string
172 }{
173 {
174 - match: matchPathRE{},
174 + match: MatchPathRE{},
175 input: "/",
176 expect: true,
177 },
178 {
179 - match: matchPathRE{matchRegexp{Pattern: "/"}},
179 + match: MatchPathRE{matchRegexp{Pattern: "/"}},
180 input: "/",
181 expect: true,
182 },
183 {
184 - match: matchPathRE{matchRegexp{Pattern: "/foo"}},
184 + match: MatchPathRE{matchRegexp{Pattern: "/foo"}},
185 input: "/foo",
186 expect: true,
187 },
188 {
189 - match: matchPathRE{matchRegexp{Pattern: "/foo"}},
189 + match: MatchPathRE{matchRegexp{Pattern: "/foo"}},
190 input: "/foo/",
191 expect: true,
192 },
193 {
194 - match: matchPathRE{matchRegexp{Pattern: "/bar"}},
194 + match: MatchPathRE{matchRegexp{Pattern: "/bar"}},
195 input: "/foo/",
196 expect: false,
197 },
198 {
199 - match: matchPathRE{matchRegexp{Pattern: "^/bar"}},
199 + match: MatchPathRE{matchRegexp{Pattern: "^/bar"}},
200 input: "/foo/bar",
201 expect: false,
202 },
203 {
204 - match: matchPathRE{matchRegexp{Pattern: "^/foo/(.*)/baz$", Name: "name"}},
204 + match: MatchPathRE{matchRegexp{Pattern: "^/foo/(.*)/baz$", Name: "name"}},
205 input: "/foo/bar/baz",
206 expect: true,
207 expectRepl: map[string]string{"name.1": "bar"},
208 },
209 {
210 - match: matchPathRE{matchRegexp{Pattern: "^/foo/(?P<myparam>.*)/baz$", Name: "name"}},
210 + match: MatchPathRE{matchRegexp{Pattern: "^/foo/(?P<myparam>.*)/baz$", Name: "name"}},
211 input: "/foo/bar/baz",
212 expect: true,
213 expectRepl: map[string]string{"name.myparam": "bar"},
@@ -253,47 +253,47 @@ func TestPathREMatcher(t *testing.T) {
253
254 func TestHeaderMatcher(t *testing.T) {
255 for i, tc := range []struct {
256 - match matchHeader
256 + match MatchHeader
257 input http.Header // make sure these are canonical cased (std lib will do that in a real request)
258 expect bool
259 }{
260 {
261 - match: matchHeader{"Field": []string{"foo"}},
261 + match: MatchHeader{"Field": []string{"foo"}},
262 input: http.Header{"Field": []string{"foo"}},
263 expect: true,
264 },
265 {
266 - match: matchHeader{"Field": []string{"foo", "bar"}},
266 + match: MatchHeader{"Field": []string{"foo", "bar"}},
267 input: http.Header{"Field": []string{"bar"}},
268 expect: true,
269 },
270 {
271 - match: matchHeader{"Field": []string{"foo", "bar"}},
271 + match: MatchHeader{"Field": []string{"foo", "bar"}},
272 input: http.Header{"Alakazam": []string{"kapow"}},
273 expect: false,
274 },
275 {
276 - match: matchHeader{"Field": []string{"foo", "bar"}},
276 + match: MatchHeader{"Field": []string{"foo", "bar"}},
277 input: http.Header{"Field": []string{"kapow"}},
278 expect: false,
279 },
280 {
281 - match: matchHeader{"Field": []string{"foo", "bar"}},
281 + match: MatchHeader{"Field": []string{"foo", "bar"}},
282 input: http.Header{"Field": []string{"kapow", "foo"}},
283 expect: true,
284 },
285 {
286 - match: matchHeader{"Field1": []string{"foo"}, "Field2": []string{"bar"}},
286 + match: MatchHeader{"Field1": []string{"foo"}, "Field2": []string{"bar"}},
287 input: http.Header{"Field1": []string{"foo"}, "Field2": []string{"bar"}},
288 expect: true,
289 },
290 {
291 - match: matchHeader{"field1": []string{"foo"}, "field2": []string{"bar"}},
291 + match: MatchHeader{"field1": []string{"foo"}, "field2": []string{"bar"}},
292 input: http.Header{"Field1": []string{"foo"}, "Field2": []string{"bar"}},
293 expect: true,
294 },
295 {
296 - match: matchHeader{"field1": []string{"foo"}, "field2": []string{"bar"}},
296 + match: MatchHeader{"field1": []string{"foo"}, "field2": []string{"bar"}},
297 input: http.Header{"Field1": []string{"foo"}, "Field2": []string{"kapow"}},
298 expect: false,
299 },
@@ -309,23 +309,23 @@ func TestHeaderMatcher(t *testing.T) {
309
310 func TestHeaderREMatcher(t *testing.T) {
311 for i, tc := range []struct {
312 - match matchHeaderRE
312 + match MatchHeaderRE
313 input http.Header // make sure these are canonical cased (std lib will do that in a real request)
314 expect bool
315 expectRepl map[string]string
316 }{
317 {
318 - match: matchHeaderRE{"Field": &matchRegexp{Pattern: "foo"}},
318 + match: MatchHeaderRE{"Field": &matchRegexp{Pattern: "foo"}},
319 input: http.Header{"Field": []string{"foo"}},
320 expect: true,
321 },
322 {
323 - match: matchHeaderRE{"Field": &matchRegexp{Pattern: "$foo^"}},
323 + match: MatchHeaderRE{"Field": &matchRegexp{Pattern: "$foo^"}},
324 input: http.Header{"Field": []string{"foobar"}},
325 expect: false,
326 },
327 {
328 - match: matchHeaderRE{"Field": &matchRegexp{Pattern: "^foo(.*)$", Name: "name"}},
328 + match: MatchHeaderRE{"Field": &matchRegexp{Pattern: "^foo(.*)$", Name: "name"}},
329 input: http.Header{"Field": []string{"foobar"}},
330 expect: true,
331 expectRepl: map[string]string{"name.1": "bar"},
modules/caddyhttp/reverseproxy/upstream.go
+2
@@ -37,6 +37,8 @@ const (
37 // TypeBalanceRandom represents the value to use for configuring a load balanced reverse proxy to use random load balancing.
38 TypeBalanceRandom
39
40 + // TODO: add random with two choices
41 +
42 // msgNoHealthyUpstreams is returned if there are no upstreams that are healthy to proxy a request to
43 msgNoHealthyUpstreams = "No healthy upstreams."
44
modules/caddyhttp/rewrite/rewrite.go
+3 -3
@@ -18,9 +18,9 @@ func init() {
18
19 // Rewrite is a middleware which can rewrite HTTP requests.
20 type Rewrite struct {
21 - Method string `json:"method"`
22 - URI string `json:"uri"`
23 - Rehandle bool `json:"rehandle"`
21 + Method string `json:"method,omitempty"`
22 + URI string `json:"uri,omitempty"`
23 + Rehandle bool `json:"rehandle,omitempty"`
24 }
25
26 func (rewr Rewrite) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
modules/caddyhttp/routes.go
+5 -5
@@ -12,12 +12,12 @@ import (
12 // middlewares, and a responder for handling HTTP
13 // requests.
14 type ServerRoute struct {
15 - Group string `json:"group"`
16 - Matchers map[string]json.RawMessage `json:"match"`
17 - Apply []json.RawMessage `json:"apply"`
18 - Respond json.RawMessage `json:"respond"`
15 + Group string `json:"group,omitempty"`
16 + Matchers map[string]json.RawMessage `json:"match,omitempty"`
17 + Apply []json.RawMessage `json:"apply,omitempty"`
18 + Respond json.RawMessage `json:"respond,omitempty"`
19
20 - Terminal bool `json:"terminal"`
20 + Terminal bool `json:"terminal,omitempty"`
21
22 // decoded values
23 matchers []RequestMatcher
modules/caddyhttp/server.go
+10 -10
@@ -13,15 +13,15 @@ import (
13
14 // Server is an HTTP server.
15 type Server struct {
16 - Listen []string `json:"listen"`
17 - ReadTimeout caddy2.Duration `json:"read_timeout"`
18 - ReadHeaderTimeout caddy2.Duration `json:"read_header_timeout"`
19 - Routes RouteList `json:"routes"`
20 - Errors httpErrorConfig `json:"errors"`
21 - TLSConnPolicies caddytls.ConnectionPolicies `json:"tls_connection_policies"`
22 - DisableAutoHTTPS bool `json:"disable_auto_https"`
23 - DisableAutoHTTPSRedir bool `json:"disable_auto_https_redir"`
24 - MaxRehandles int `json:"max_rehandles"`
16 + Listen []string `json:"listen,omitempty"`
17 + ReadTimeout caddy2.Duration `json:"read_timeout,omitempty"`
18 + ReadHeaderTimeout caddy2.Duration `json:"read_header_timeout,omitempty"`
19 + Routes RouteList `json:"routes,omitempty"`
20 + Errors *httpErrorConfig `json:"errors,omitempty"`
21 + TLSConnPolicies caddytls.ConnectionPolicies `json:"tls_connection_policies,omitempty"`
22 + DisableAutoHTTPS bool `json:"disable_auto_https,omitempty"`
23 + DisableAutoHTTPSRedir bool `json:"disable_auto_https_redir,omitempty"`
24 + MaxRehandles int `json:"max_rehandles,omitempty"`
25
26 tlsApp *caddytls.TLS
27 }
@@ -99,7 +99,7 @@ func (s *Server) executeCompositeRoute(w http.ResponseWriter, r *http.Request, s
99 }
100
101 type httpErrorConfig struct {
102 - Routes RouteList `json:"routes"`
102 + Routes RouteList `json:"routes,omitempty"`
103 // TODO: some way to configure the logging of errors, probably? standardize
104 // the logging configuration first.
105 }