cmd/golangorg: clean up, centralize handler registration

All handlers (except the App Engine production ones) should
be registered on the mux protected by hostEnforcerHandler.
Do that, and sort the registrations for easy scanning (by people).

Change-Id: I96813eb105f63bf37abed4898ccf23d1f16cc8d4
Reviewed-on: https://go-review.googlesource.com/c/website/+/293416
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
This commit is contained in:
Russ Cox 2021-02-16 22:49:26 -05:00
Родитель e37fc2d9d4
Коммит 44a429fa8f
6 изменённых файлов: 21 добавлений и 126 удалений

Просмотреть файл

@ -1,88 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16
// +build go1.16
package main
import (
"fmt"
"go/build"
"log"
"net/http"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
"golang.org/x/tools/blog"
"golang.org/x/website/internal/redirect"
)
const (
blogRepo = "golang.org/x/blog"
blogURL = "https://blog.golang.org/"
blogPath = "/blog/"
)
var (
blogServer http.Handler // set by blogInit
blogInitOnce sync.Once
playEnabled bool
)
func init() {
// Initialize blog only when first accessed.
http.HandleFunc(blogPath, func(w http.ResponseWriter, r *http.Request) {
blogInitOnce.Do(func() {
blogInit(r.Host)
})
blogServer.ServeHTTP(w, r)
})
}
func blogInit(host string) {
// Binary distributions included the blog content in "/blog".
// We stopped including this in Go 1.11.
root := filepath.Join(runtime.GOROOT(), "blog")
// Prefer content from the golang.org/x/blog repository if present.
if pkg, err := build.Import(blogRepo, "", build.FindOnly); err == nil {
root = pkg.Dir
}
// If content is not available fall back to redirect.
if fi, err := os.Stat(root); err != nil || !fi.IsDir() {
fmt.Fprintf(os.Stderr, "Blog content not available locally. "+
"To install, run \n\tgo get %v\n", blogRepo)
blogServer = http.HandlerFunc(blogRedirectHandler)
return
}
s, err := blog.NewServer(blog.Config{
BaseURL: blogPath,
BasePath: strings.TrimSuffix(blogPath, "/"),
ContentPath: filepath.Join(root, "content"),
TemplatePath: filepath.Join(root, "template"),
HomeArticles: 5,
PlayEnabled: playEnabled,
ServeLocalLinks: strings.HasPrefix(host, "localhost"),
})
if err != nil {
log.Fatal(err)
}
blogServer = s
}
func blogRedirectHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == blogPath {
http.Redirect(w, r, blogURL, http.StatusFound)
return
}
blogPrefixHandler.ServeHTTP(w, r)
}
var blogPrefixHandler = redirect.PrefixHandler(blogPath, blogURL)

Просмотреть файл

@ -75,14 +75,16 @@ func registerHandlers(pres *godoc.Presentation) *http.ServeMux {
panic("nil Presentation")
}
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/"))
mux.HandleFunc("/fmt", fmtHandler)
mux.Handle("/blog/", http.HandlerFunc(blogHandler))
mux.Handle("/doc/codewalk/", http.HandlerFunc(codewalk))
mux.Handle("/doc/devel/release.html", releaseHandler{ReleaseHistory: sortReleases(history.Releases)})
handleRootAndSubtree(mux, "/project/", projectHandler{ReleaseHistory: sortMajorReleases(history.Releases)}, pres)
mux.Handle("/doc/play/", pres.FileServer())
mux.Handle("/fmt", http.HandlerFunc(fmtHandler))
mux.Handle("/pkg/C/", redirect.Handler("/cmd/cgo/"))
mux.Handle("/project/", projectHandler{ReleaseHistory: sortMajorReleases(history.Releases)})
mux.Handle("/robots.txt", pres.FileServer())
mux.Handle("/x/", http.HandlerFunc(xHandler))
redirect.Register(mux)
http.Handle("/", hostEnforcerHandler{mux})
@ -90,26 +92,6 @@ func registerHandlers(pres *godoc.Presentation) *http.ServeMux {
return mux
}
// handleRootAndSubtree registers a handler for the given pattern in mux.
// The handler selects between root or subtree handlers to handle requests.
//
// The root handler is used for requests with URL path equal to the pattern,
// and the subtree handler is used for all other requests matched by pattern.
//
// The pattern must have a trailing slash ('/'), otherwise handleRoot panics.
func handleRootAndSubtree(mux *http.ServeMux, path string, root, subtree http.Handler) {
if !strings.HasSuffix(path, "/") {
panic("handleRootAndSubtree must be used on patterns with a trailing slash ('/')")
}
mux.HandleFunc(path, func(w http.ResponseWriter, req *http.Request) {
if req.URL.Path == path {
root.ServeHTTP(w, req)
} else {
subtree.ServeHTTP(w, req)
}
})
}
func readTemplate(name string) *template.Template {
if pres == nil {
panic("no global Presentation set yet")
@ -164,3 +146,7 @@ func fmtHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(resp)
}
func blogHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "https://blog.golang.org"+strings.TrimPrefix(r.URL.Path, "/blog"), http.StatusFound)
}

Просмотреть файл

@ -36,5 +36,5 @@ func earlySetup() {
func lateSetup(mux *http.ServeMux) {
// Register a redirect handler for /dl/ to the golang.org download page.
http.Handle("/dl/", http.RedirectHandler("https://golang.org/dl/", http.StatusFound))
mux.Handle("/dl/", http.RedirectHandler("https://golang.org/dl/", http.StatusFound))
}

Просмотреть файл

@ -65,8 +65,6 @@ func main() {
flag.Usage = usage
flag.Parse()
playEnabled = *showPlayground
// Check usage.
if flag.NArg() > 0 {
fmt.Fprintln(os.Stderr, "Unexpected arguments.")

Просмотреть файл

@ -20,12 +20,17 @@ import (
"golang.org/x/website/internal/history"
)
// projectHandler serves The Go Project page.
// projectHandler serves The Go Project page on /project/.
type projectHandler struct {
ReleaseHistory []MajorRelease // Pre-computed release history to display.
}
func (h projectHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if req.URL.Path != "/project/" {
pres.ServeHTTP(w, req) // 404
return
}
const relPath = "doc/contrib.html"
src, err := vfs.ReadFile(fs, relPath)

Просмотреть файл

@ -20,19 +20,13 @@ import (
"golang.org/x/build/repos"
)
const xPrefix = "/x/"
func init() {
http.HandleFunc(xPrefix, xHandler)
}
func xHandler(w http.ResponseWriter, r *http.Request) {
if !strings.HasPrefix(r.URL.Path, xPrefix) {
if !strings.HasPrefix(r.URL.Path, "/x/") {
// Shouldn't happen if handler is registered correctly.
http.Redirect(w, r, "https://pkg.go.dev/search?q=golang.org/x", http.StatusTemporaryRedirect)
return
}
proj, suffix := strings.TrimPrefix(r.URL.Path, xPrefix), ""
proj, suffix := strings.TrimPrefix(r.URL.Path, "/x/"), ""
if i := strings.Index(proj, "/"); i != -1 {
proj, suffix = proj[:i], proj[i:]
}