summaryrefslogtreecommitdiff
path: root/modules/caddyhttp/routes.go
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2019-05-20 10:59:20 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2019-05-20 10:59:20 -0600
commitfec7fa8bfda713e8042b9bbf9a480c7792b78c41 (patch)
tree53d86ab50ef7d15e9688c81b6618024c4243c98d /modules/caddyhttp/routes.go
parent1a20fe330ecc39e8b98b5669b836f3b1b185f622 (diff)
Implement most of static file server; refactor and improve Replacer
Diffstat (limited to 'modules/caddyhttp/routes.go')
-rw-r--r--modules/caddyhttp/routes.go53
1 files changed, 49 insertions, 4 deletions
diff --git a/modules/caddyhttp/routes.go b/modules/caddyhttp/routes.go
index d204939..daae080 100644
--- a/modules/caddyhttp/routes.go
+++ b/modules/caddyhttp/routes.go
@@ -12,6 +12,7 @@ import (
// middlewares, and a responder for handling HTTP
// requests.
type ServerRoute struct {
+ Group string `json:"group"`
Matchers map[string]json.RawMessage `json:"match"`
Apply []json.RawMessage `json:"apply"`
Respond json.RawMessage `json:"respond"`
@@ -19,7 +20,7 @@ type ServerRoute struct {
Terminal bool `json:"terminal"`
// decoded values
- matchers []RouteMatcher
+ matchers []RequestMatcher
middleware []MiddlewareHandler
responder Handler
}
@@ -37,7 +38,7 @@ func (routes RouteList) Provision(ctx caddy2.Context) error {
if err != nil {
return fmt.Errorf("loading matcher module '%s': %v", modName, err)
}
- routes[i].matchers = append(routes[i].matchers, val.(RouteMatcher))
+ routes[i].matchers = append(routes[i].matchers, val.(RequestMatcher))
}
routes[i].Matchers = nil // allow GC to deallocate - TODO: Does this help?
@@ -64,9 +65,9 @@ func (routes RouteList) Provision(ctx caddy2.Context) error {
return nil
}
-// BuildHandlerChain creates a chain of handlers by
+// BuildCompositeRoute creates a chain of handlers by
// applying all the matching routes.
-func (routes RouteList) BuildHandlerChain(w http.ResponseWriter, r *http.Request) Handler {
+func (routes RouteList) BuildCompositeRoute(w http.ResponseWriter, r *http.Request) Handler {
if len(routes) == 0 {
return emptyHandler
}
@@ -74,17 +75,39 @@ func (routes RouteList) BuildHandlerChain(w http.ResponseWriter, r *http.Request
var mid []Middleware
var responder Handler
mrw := &middlewareResponseWriter{ResponseWriterWrapper: &ResponseWriterWrapper{w}}
+ groups := make(map[string]struct{})
routeLoop:
for _, route := range routes {
+ // see if route matches
for _, m := range route.matchers {
if !m.Match(r) {
continue routeLoop
}
}
+
+ // if route is part of a group, ensure only
+ // the first matching route in the group is
+ // applied
+ if route.Group != "" {
+ _, ok := groups[route.Group]
+ if ok {
+ // this group has already been satisfied
+ // by a matching route
+ continue
+ }
+ // this matching route satisfies the group
+ groups[route.Group] = struct{}{}
+ }
+
+ // apply the rest of the route
for _, m := range route.middleware {
mid = append(mid, func(next HandlerFunc) HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
+ // TODO: This is where request tracing could be implemented; also
+ // see below to trace the responder as well
+ // TODO: Trace a diff of the request, would be cool too! see what changed since the last middleware (host, headers, URI...)
+ // TODO: see what the std lib gives us in terms of stack trracing too
return m.ServeHTTP(mrw, r, next)
}
})
@@ -111,3 +134,25 @@ routeLoop:
return stack
}
+
+type middlewareResponseWriter struct {
+ *ResponseWriterWrapper
+ allowWrites bool
+}
+
+func (mrw middlewareResponseWriter) WriteHeader(statusCode int) {
+ if !mrw.allowWrites {
+ panic("WriteHeader: middleware cannot write to the response")
+ }
+ mrw.ResponseWriterWrapper.WriteHeader(statusCode)
+}
+
+func (mrw middlewareResponseWriter) Write(b []byte) (int, error) {
+ if !mrw.allowWrites {
+ panic("Write: middleware cannot write to the response")
+ }
+ return mrw.ResponseWriterWrapper.Write(b)
+}
+
+// Interface guard
+var _ HTTPInterfaces = middlewareResponseWriter{}