in cmd/golangorg/server.go [134:242]
func NewHandler(contentDir, goroot string) http.Handler {
mux := http.NewServeMux()
// Serve files from _content, falling back to GOROOT.
// Use explicit contentDir if specified, otherwise embedded copy.
var contentFS fs.FS
if contentDir != "" {
contentFS = os.DirFS(contentDir)
} else {
contentFS = website.Content()
}
var gorootFS fs.FS
if strings.HasSuffix(goroot, ".zip") {
z, err := zip.OpenReader(goroot)
if err != nil {
log.Fatal(err)
}
gorootFS = &seekableFS{z}
} else {
gorootFS = os.DirFS(goroot)
}
// tip.golang.org serves content from the very latest Git commit
// of the main Go repo, instead of the one the app is bundled with.
var tipGoroot atomicFS
if _, err := newSite(mux, "tip.golang.org", contentFS, &tipGoroot); err != nil {
log.Fatalf("loading tip site: %v", err)
}
if *tipFlag {
go watchTip(&tipGoroot)
}
// beta.golang.org is an old name for tip.
mux.Handle("beta.golang.org/", redirectPrefix("https://tip.golang.org/"))
// By default, golang.org/foo redirects to go.dev/foo.
// All the user-facing golang.org subdomains have moved to go.dev subdirectories.
// There are some exceptions below, like for golang.org/x.
mux.Handle("golang.org/", redirectPrefix("https://go.dev/"))
mux.Handle("blog.golang.org/", redirectPrefix("https://go.dev/blog/"))
mux.Handle("learn.go.dev/", redirectPrefix("https://go.dev/learn/"))
mux.Handle("talks.golang.org/", redirectPrefix("https://go.dev/talks/"))
mux.Handle("tour.golang.org/", redirectPrefix("https://go.dev/tour/"))
// Redirect subdirectory-like domains to the actual subdirectories,
// for people whose fingers learn to type go.dev instead of golang.org
// but not the rest of the URL schema change.
// Note that these domains have to be listed in knownHosts below as well.
mux.Handle("blog.go.dev/", redirectPrefix("https://go.dev/blog/"))
mux.Handle("play.go.dev/", redirectPrefix("https://go.dev/play/"))
mux.Handle("talks.go.dev/", redirectPrefix("https://go.dev/talks/"))
mux.Handle("tour.go.dev/", redirectPrefix("https://go.dev/tour/"))
// m.golang.org is an old shortcut for golang.org mail.
// Gmail itself can serve this redirect, but only on HTTP (not HTTPS).
// Golang.org's HSTS header tells browsers to use HTTPS for all subdomains,
// which broke the redirect.
mux.Handle("m.golang.org/", http.RedirectHandler("https://mail.google.com/a/golang.org/", http.StatusMovedPermanently))
// Register a redirect handler for tip.golang.org/dl/ to the golang.org download page.
// (golang.org/dl and golang.google.cn/dl are registered separately.)
mux.Handle("tip.golang.org/dl/", http.RedirectHandler("https://go.dev/dl/", http.StatusFound))
// TODO(rsc): The unionFS is a hack until we move the files in a followup CL.
siteMux := http.NewServeMux()
godevSite, err := newSite(siteMux, "", contentFS, gorootFS)
if err != nil {
log.Fatalf("newSite go.dev: %v", err)
}
chinaSite, err := newSite(siteMux, "golang.google.cn", contentFS, gorootFS)
if err != nil {
log.Fatalf("newSite golang.google.cn: %v", err)
}
if runningOnAppEngine {
appEngineSetup(mux)
}
dl.RegisterHandlers(siteMux, godevSite, "", datastoreClient, memcacheClient)
dl.RegisterHandlers(siteMux, chinaSite, "golang.google.cn", datastoreClient, memcacheClient)
mux.Handle("/", siteMux)
play.RegisterHandlers(mux, godevSite, chinaSite)
mux.Handle("/explore/", http.StripPrefix("/explore/", redirectPrefix("https://pkg.go.dev/")))
if err := blog.RegisterFeeds(mux, "", godevSite); err != nil {
log.Fatalf("blog: %v", err)
}
// Note: Only golang.org/x/, no go.dev/x/.
mux.Handle("golang.org/x/", http.HandlerFunc(xHandler))
redirect.Register(mux)
// Note: Using godevSite (non-China) for global mux registration because there's no sharing in talks.
// Don't need the hassle of two separate registrations for different domains in siteMux.
if err := talks.RegisterHandlers(mux, godevSite, contentFS); err != nil {
log.Fatalf("talks: %v", err)
}
if err := tour.RegisterHandlers(mux); err != nil {
log.Fatalf("tour: %v", err)
}
var h http.Handler = mux
h = addCSP(mux)
h = hostEnforcerHandler(h)
h = hostPathHandler(h)
return h
}