mirror of
https://github.com/golang/go
synced 2024-11-18 13:14:47 -07:00
bd17c084df
This change replaces the env package with a new golangorgenv package. The previous env package existed primarily to configure the godoc instance that was running golang.org. By now, the golang.org website has been factored out to x/website, which has its own env package, but ends up still using this env package indirectly via x/tools/godoc. The goal of this change is to make env available for other services that run on subdomains of golang.org, so they can continue to safely rely on the x/tools/playground, which will be modified in the next commit to also use the new golangorgenv. The golangorgenv package replaces the IsProd function with a more specific one. Start using it in packages x/tools/{,cmd}/godoc. Also, re-arrange the order of checks to give the host suffix check higher priority than the environment variable check. This way, if the environment variable isn't set, the host suffix check gets a chance to run. When getting the value of "X-AppEngine-Country" header, use its canonical format "X-Appengine-Country" to avoid an allocation. This does not change behavior. Updates golang/go#30486 Change-Id: I97b47211a45ca0351f31fcb4fa6d408a4b0c4c7c Reviewed-on: https://go-review.googlesource.com/c/tools/+/165459 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
152 lines
4.3 KiB
Go
152 lines
4.3 KiB
Go
// Copyright 2010 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.
|
|
|
|
// The /doc/codewalk/ tree is synthesized from codewalk descriptions,
|
|
// files named $GOROOT/doc/codewalk/*.xml.
|
|
// For an example and a description of the format, see
|
|
// http://golang.org/doc/codewalk/codewalk or run godoc -http=:6060
|
|
// and see http://localhost:6060/doc/codewalk/codewalk .
|
|
// That page is itself a codewalk; the source code for it is
|
|
// $GOROOT/doc/codewalk/codewalk.xml.
|
|
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"go/format"
|
|
"log"
|
|
"net/http"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"golang.org/x/tools/godoc"
|
|
"golang.org/x/tools/godoc/golangorgenv"
|
|
"golang.org/x/tools/godoc/redirect"
|
|
"golang.org/x/tools/godoc/vfs"
|
|
)
|
|
|
|
var (
|
|
pres *godoc.Presentation
|
|
fs = vfs.NameSpace{}
|
|
)
|
|
|
|
// 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 and
|
|
// golang.google.cn for Chinese users.
|
|
type hostEnforcerHandler struct {
|
|
h http.Handler
|
|
}
|
|
|
|
func (h hostEnforcerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
if !golangorgenv.EnforceHosts() {
|
|
h.h.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
if !h.isHTTPS(r) || !h.validHost(r.Host) {
|
|
r.URL.Scheme = "https"
|
|
if h.validHost(r.Host) {
|
|
r.URL.Host = r.Host
|
|
} else {
|
|
r.URL.Host = "golang.org"
|
|
}
|
|
http.Redirect(w, r, r.URL.String(), http.StatusFound)
|
|
return
|
|
}
|
|
w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
|
|
h.h.ServeHTTP(w, r)
|
|
}
|
|
|
|
func (h hostEnforcerHandler) isHTTPS(r *http.Request) bool {
|
|
return r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https"
|
|
}
|
|
|
|
func (h hostEnforcerHandler) validHost(host string) bool {
|
|
switch strings.ToLower(host) {
|
|
case "golang.org", "golang.google.cn":
|
|
return true
|
|
}
|
|
if strings.HasSuffix(host, "-dot-golang-org.appspot.com") {
|
|
// staging/test
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func registerHandlers(pres *godoc.Presentation) *http.ServeMux {
|
|
if pres == nil {
|
|
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)
|
|
redirect.Register(mux)
|
|
|
|
http.Handle("/", hostEnforcerHandler{mux})
|
|
|
|
return mux
|
|
}
|
|
|
|
func readTemplate(name string) *template.Template {
|
|
if pres == nil {
|
|
panic("no global Presentation set yet")
|
|
}
|
|
path := "lib/godoc/" + name
|
|
|
|
// use underlying file system fs to read the template file
|
|
// (cannot use template ParseFile functions directly)
|
|
data, err := vfs.ReadFile(fs, path)
|
|
if err != nil {
|
|
log.Fatal("readTemplate: ", err)
|
|
}
|
|
// be explicit with errors (for app engine use)
|
|
t, err := template.New(name).Funcs(pres.FuncMap()).Parse(string(data))
|
|
if err != nil {
|
|
log.Fatal("readTemplate: ", err)
|
|
}
|
|
return t
|
|
}
|
|
|
|
func readTemplates(p *godoc.Presentation) {
|
|
codewalkHTML = readTemplate("codewalk.html")
|
|
codewalkdirHTML = readTemplate("codewalkdir.html")
|
|
p.CallGraphHTML = readTemplate("callgraph.html")
|
|
p.DirlistHTML = readTemplate("dirlist.html")
|
|
p.ErrorHTML = readTemplate("error.html")
|
|
p.ExampleHTML = readTemplate("example.html")
|
|
p.GodocHTML = readTemplate("godoc.html")
|
|
p.ImplementsHTML = readTemplate("implements.html")
|
|
p.MethodSetHTML = readTemplate("methodset.html")
|
|
p.PackageHTML = readTemplate("package.html")
|
|
p.PackageRootHTML = readTemplate("packageroot.html")
|
|
p.SearchHTML = readTemplate("search.html")
|
|
p.SearchDocHTML = readTemplate("searchdoc.html")
|
|
p.SearchCodeHTML = readTemplate("searchcode.html")
|
|
p.SearchTxtHTML = readTemplate("searchtxt.html")
|
|
p.SearchDescXML = readTemplate("opensearch.xml")
|
|
}
|
|
|
|
type fmtResponse struct {
|
|
Body string
|
|
Error string
|
|
}
|
|
|
|
// fmtHandler takes a Go program in its "body" form value, formats it with
|
|
// standard gofmt formatting, and writes a fmtResponse as a JSON object.
|
|
func fmtHandler(w http.ResponseWriter, r *http.Request) {
|
|
resp := new(fmtResponse)
|
|
body, err := format.Source([]byte(r.FormValue("body")))
|
|
if err != nil {
|
|
resp.Error = err.Error()
|
|
} else {
|
|
resp.Body = string(body)
|
|
}
|
|
w.Header().Set("Content-type", "application/json; charset=utf-8")
|
|
json.NewEncoder(w).Encode(resp)
|
|
}
|