about summary refs log tree commit diff stats
path: root/internal/server/server.go
diff options
context:
space:
mode:
authorAlan Pearce2024-06-27 11:04:06 +0200
committerAlan Pearce2024-06-27 11:07:17 +0200
commitdb122cd2fd0c7210acafc3752dcffe926370cc28 (patch)
treeff49c00b98d95277da0a5f2e6697190c844f3e12 /internal/server/server.go
parent765a227bbf42983a9edb3eaac6e48df7a43f2808 (diff)
downloadwebsite-db122cd2fd0c7210acafc3752dcffe926370cc28.tar.lz
website-db122cd2fd0c7210acafc3752dcffe926370cc28.tar.zst
website-db122cd2fd0c7210acafc3752dcffe926370cc28.zip
avoid redirect chains (http -> https, host1 -> host2)
Diffstat (limited to 'internal/server/server.go')
-rw-r--r--internal/server/server.go39
1 files changed, 30 insertions, 9 deletions
diff --git a/internal/server/server.go b/internal/server/server.go
index 0f7701a..1512632 100644
--- a/internal/server/server.go
+++ b/internal/server/server.go
@@ -47,8 +47,9 @@ type Config struct {
 
 type Server struct {
 	*http.Server
-	runtimeConfig *Config
-	config        *cfg.Config
+	redirectHandler func(http.ResponseWriter, *http.Request)
+	runtimeConfig   *Config
+	config          *cfg.Config
 }
 
 func applyDevModeOverrides(config *cfg.Config, runtimeConfig *Config) {
@@ -59,9 +60,13 @@ func applyDevModeOverrides(config *cfg.Config, runtimeConfig *Config) {
 	} else {
 		config.Domains = []string{runtimeConfig.ListenAddress}
 	}
+	scheme := "http"
+	if runtimeConfig.TLS {
+		scheme = "https"
+	}
 	config.BaseURL = cfg.URL{
 		URL: &url.URL{
-			Scheme: "http",
+			Scheme: scheme,
 			Host:   runtimeConfig.ListenAddress,
 		},
 	}
@@ -76,9 +81,22 @@ func updateCSPHashes(config *cfg.Config, r *builder.Result) {
 
 func serverHeaderHandler(wrappedHandler http.Handler) http.Handler {
 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		log.Debug(
+			"headers",
+			"proto",
+			r.Header.Get("X-Forwarded-Proto"),
+			"host",
+			r.Header.Get("X-Forwarded-Host"),
+			"scheme",
+			r.URL.Scheme,
+			"secure",
+			r.TLS != nil,
+		)
+		log.Debug("host", "request", r.Host, "header", r.Header.Get("Host"))
 		if r.ProtoMajor >= 2 && r.Header.Get("Host") != "" {
 			// net/http does this for HTTP/1.1, but not h2c
 			// TODO: check with HTTP/2.0 (i.e. with TLS)
+			log.Debug("host", "request", r.Host, "header", r.Header.Get("Host"))
 			r.Host = r.Header.Get("Host")
 			r.Header.Del("Host")
 		}
@@ -174,12 +192,14 @@ func New(runtimeConfig *Config) (*Server, error) {
 		return nil, errors.Wrap(err, "could not create website mux")
 	}
 
+	redirectHandler := func(w http.ResponseWriter, r *http.Request) {
+		path, _ := website.CanonicalisePath(r.URL.Path)
+		newURL := config.BaseURL.JoinPath(path)
+		http.Redirect(w, r, newURL.String(), 301)
+	}
 	if runtimeConfig.Redirect {
 		loggingMux.Handle(config.BaseURL.Hostname()+"/", mux)
-		loggingMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
-			newURL := config.BaseURL.JoinPath(r.URL.String())
-			http.Redirect(w, r, newURL.String(), 301)
-		})
+		loggingMux.HandleFunc("/", redirectHandler)
 	} else {
 		loggingMux.Handle("/", mux)
 	}
@@ -205,8 +225,9 @@ func New(runtimeConfig *Config) (*Server, error) {
 				},
 			), 0),
 		},
-		config:        config,
-		runtimeConfig: runtimeConfig,
+		redirectHandler: redirectHandler,
+		config:          config,
+		runtimeConfig:   runtimeConfig,
 	}, nil
 }