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:
Родитель
e37fc2d9d4
Коммит
44a429fa8f
|
@ -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:]
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче