diff options
author | Matthew Holt <mholt@users.noreply.github.com> | 2019-05-20 10:59:20 -0600 |
---|---|---|
committer | Matthew Holt <mholt@users.noreply.github.com> | 2019-05-20 10:59:20 -0600 |
commit | fec7fa8bfda713e8042b9bbf9a480c7792b78c41 (patch) | |
tree | 53d86ab50ef7d15e9688c81b6618024c4243c98d /modules/caddyhttp/caddyhttp.go | |
parent | 1a20fe330ecc39e8b98b5669b836f3b1b185f622 (diff) |
Implement most of static file server; refactor and improve Replacer
Diffstat (limited to 'modules/caddyhttp/caddyhttp.go')
-rw-r--r-- | modules/caddyhttp/caddyhttp.go | 117 |
1 files changed, 17 insertions, 100 deletions
diff --git a/modules/caddyhttp/caddyhttp.go b/modules/caddyhttp/caddyhttp.go index 0fe9c98..449d07f 100644 --- a/modules/caddyhttp/caddyhttp.go +++ b/modules/caddyhttp/caddyhttp.go @@ -45,7 +45,13 @@ type App struct { func (app *App) Provision(ctx caddy2.Context) error { app.ctx = ctx + repl := caddy2.NewReplacer() + for _, srv := range app.Servers { + // TODO: Test this function to ensure these replacements are performed + for i := range srv.Listen { + srv.Listen[i] = repl.ReplaceAll(srv.Listen[i], "") + } err := srv.Routes.Provision(ctx) if err != nil { return fmt.Errorf("setting up server routes: %v", err) @@ -78,6 +84,13 @@ func (app *App) Validate() error { } } + // each server's max rehandle value must be valid + for srvName, srv := range app.Servers { + if srv.MaxRehandles < 0 { + return fmt.Errorf("%s: invalid max_rehandles value: %d", srvName, srv.MaxRehandles) + } + } + return nil } @@ -231,7 +244,7 @@ func (app *App) automaticHTTPS() error { redirTo += "{request.uri}" redirRoutes = append(redirRoutes, ServerRoute{ - matchers: []RouteMatcher{ + matchers: []RequestMatcher{ matchProtocol("http"), matchHost(domains), }, @@ -292,84 +305,9 @@ func (app *App) listenerTaken(network, address string) bool { var defaultALPN = []string{"h2", "http/1.1"} -// Server is an HTTP server. -type Server struct { - Listen []string `json:"listen"` - ReadTimeout caddy2.Duration `json:"read_timeout"` - ReadHeaderTimeout caddy2.Duration `json:"read_header_timeout"` - HiddenFiles []string `json:"hidden_files"` // TODO:... experimenting with shared/common state - Routes RouteList `json:"routes"` - Errors httpErrorConfig `json:"errors"` - TLSConnPolicies caddytls.ConnectionPolicies `json:"tls_connection_policies"` - DisableAutoHTTPS bool `json:"disable_auto_https"` - DisableAutoHTTPSRedir bool `json:"disable_auto_https_redir"` - - tlsApp *caddytls.TLS -} - -type httpErrorConfig struct { - Routes RouteList `json:"routes"` - // TODO: some way to configure the logging of errors, probably? standardize - // the logging configuration first. -} - -// ServeHTTP is the entry point for all HTTP requests. -func (s Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if s.tlsApp.HandleHTTPChallenge(w, r) { - return - } - - // set up the replacer - repl := NewReplacer(r, w) - ctx := context.WithValue(r.Context(), ReplacerCtxKey, repl) - r = r.WithContext(ctx) - - // build and execute the main middleware chain - stack := s.Routes.BuildHandlerChain(w, r) - err := executeMiddlewareChain(w, r, stack) - if err != nil { - // add the error value to the request context so - // it can be accessed by error handlers - c := context.WithValue(r.Context(), ErrorCtxKey, err) - r = r.WithContext(c) - // TODO: add error values to Replacer - - if len(s.Errors.Routes) == 0 { - // TODO: implement a default error handler? - log.Printf("[ERROR] %s", err) - } else { - errStack := s.Errors.Routes.BuildHandlerChain(w, r) - err := executeMiddlewareChain(w, r, errStack) - if err != nil { - // TODO: what should we do if the error handler has an error? - log.Printf("[ERROR] handling error: %v", err) - } - } - } -} - -// executeMiddlewareChain executes stack with w and r. This function handles -// the special ErrRehandle error value, which reprocesses requests through -// the stack again. Any error value returned from this function would be an -// actual error that needs to be handled. -func executeMiddlewareChain(w http.ResponseWriter, r *http.Request, stack Handler) error { - const maxRehandles = 3 - var err error - for i := 0; i < maxRehandles; i++ { - err = stack.ServeHTTP(w, r) - if err != ErrRehandle { - break - } - if i == maxRehandles-1 { - return fmt.Errorf("too many rehandles") - } - } - return err -} - -// RouteMatcher is a type that can match to a request. +// RequestMatcher is a type that can match to a request. // A route matcher MUST NOT modify the request. -type RouteMatcher interface { +type RequestMatcher interface { Match(*http.Request) bool } @@ -421,7 +359,6 @@ func parseListenAddr(a string) (network string, addrs []string, err error) { if err != nil { return } - host = NewReplacer(nil, nil).Replace(host, "") ports := strings.SplitN(port, "-", 2) if len(ports) == 1 { ports = append(ports, ports[0]) @@ -466,25 +403,6 @@ func joinListenAddr(network, host, port string) string { return a } -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) -} - const ( // DefaultHTTPPort is the default port for HTTP. DefaultHTTPPort = 80 @@ -493,6 +411,5 @@ const ( DefaultHTTPSPort = 443 ) -// Interface guards -var _ HTTPInterfaces = middlewareResponseWriter{} +// Interface guard var _ caddy2.App = (*App)(nil) |