internal/primarydomain/middleware.go (60 lines of code) (raw):
package primarydomain
import (
"net"
"net/http"
"strings"
"gitlab.com/gitlab-org/gitlab-pages/internal/domain"
"gitlab.com/gitlab-org/gitlab-pages/internal/logging"
"gitlab.com/gitlab-org/gitlab-pages/internal/utils"
)
func NewMiddleware(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
primaryURL := getPrimaryURL(r)
if primaryURL == "" {
logging.
LogRequest(r).
Debug("default domain: doing nothing")
handler.ServeHTTP(w, r)
return
}
logging.
LogRequest(r).
WithField("primaryURL", primaryURL).
Info("redirecting to primary domain")
http.Redirect(w, r, primaryURL, http.StatusPermanentRedirect)
})
}
var getPrimaryDomainAndPrefixFunc = getPrimaryDomainAndPrefix
func getPrimaryURL(r *http.Request) string {
primaryDomain, prefix := getPrimaryDomainAndPrefixFunc(r)
if primaryDomain == "" {
return ""
}
requestHost, _, err := net.SplitHostPort(r.Host)
if err != nil {
requestHost = r.Host
}
primaryURL, isValid := utils.ParseURL(primaryDomain)
if !isValid {
return ""
}
// If the requestHost is already the primaryDomain, no need to redirect
if requestHost == primaryURL.Host {
return ""
}
// Ensure to redirect to the same path requested
primaryURL.Path = strings.TrimPrefix(
r.URL.Path,
strings.TrimSuffix(prefix, "/"),
)
return primaryURL.String()
}
func getPrimaryDomainAndPrefix(r *http.Request) (string, string) {
lookupPath, err := domain.FromRequest(r).GetLookupPath(r)
if err != nil {
logging.
LogRequest(r).
WithError(err).
Error("primaryDomain: failed to get lookupPath")
return "", ""
}
return lookupPath.PrimaryDomain, lookupPath.Prefix
}