diff --git a/cmd/godoc/appinit.go b/cmd/godoc/appinit.go index 3d6a9210e8..c2c166aec6 100644 --- a/cmd/godoc/appinit.go +++ b/cmd/godoc/appinit.go @@ -20,9 +20,12 @@ import ( "golang.org/x/tools/godoc/vfs" "golang.org/x/tools/godoc/vfs/mapfs" "golang.org/x/tools/godoc/vfs/zipfs" + + "appengine" ) func init() { + enforceHosts = !appengine.IsDevAppServer() playEnabled = true log.Println("initializing godoc ...") diff --git a/cmd/godoc/handlers.go b/cmd/godoc/handlers.go index 1f79d80d78..5919a6feb2 100644 --- a/cmd/godoc/handlers.go +++ b/cmd/godoc/handlers.go @@ -15,6 +15,7 @@ package main import ( "log" "net/http" + "strings" "text/template" "golang.org/x/tools/godoc" @@ -27,16 +28,51 @@ var ( fs = vfs.NameSpace{} ) +var enforceHosts = false // set true in production on app engine + +// hostEnforcerHandler redirects requests to "http://foo.golang.org/bar" +// to "https://golang.org/bar". +// It permits requests to the host "godoc-test.golang.org" for testing. +type hostEnforcerHandler struct { + h http.Handler +} + +func (h hostEnforcerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if !enforceHosts { + h.h.ServeHTTP(w, r) + return + } + if r.TLS == nil || !h.validHost(r.Host) { + r.URL.Scheme = "https" + if !h.validHost(r.Host) { + r.URL.Host = "golang.org" + } + http.Redirect(w, r, r.URL.String(), http.StatusFound) + return + } + h.h.ServeHTTP(w, r) +} + +func (h hostEnforcerHandler) validHost(host string) bool { + switch strings.ToLower(host) { + case "golang.org", "godoc-test.golang.org": + return true + } + return false +} + func registerHandlers(pres *godoc.Presentation) { if pres == nil { panic("nil Presentation") } - http.HandleFunc("/doc/codewalk/", codewalk) - http.Handle("/doc/play/", pres.FileServer()) - http.Handle("/robots.txt", pres.FileServer()) - http.Handle("/", pres) - http.Handle("/pkg/C/", redirect.Handler("/cmd/cgo/")) - redirect.Register(nil) + mux := http.NewServeMux() + mux.HandleFunc("/doc/codewalk/", codewalk) + mux.Handle("/doc/play/", pres.FileServer()) + mux.Handle("/robots.txt", pres.FileServer()) + mux.Handle("/", pres) + mux.Handle("/pkg/C/", redirect.Handler("/cmd/cgo/")) + redirect.Register(mux) + http.Handle("/", hostEnforcerHandler{mux}) } func readTemplate(name string) *template.Template {