internal/web: redirect golang.org/pkg/... to pkg.go.dev/...

This reduces the number of documentation sites we have to one.
Except in China, where we have to keep serving on the one domain
golang.google.cn - there is no pkg.go.dev in China.
And unless people opt out with ?m=old.

For golang/go#44356.

Change-Id: I2a5b788ac861ce37f356287413468497d184fc09
Reviewed-on: https://go-review.googlesource.com/c/website/+/327849
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
This commit is contained in:
Russ Cox 2021-06-09 11:33:40 -04:00
Родитель f481c2bd18
Коммит aa5eb5fcb4
7 изменённых файлов: 105 добавлений и 12 удалений

60
cmd/golangorg/testdata/web.txt поставляемый
Просмотреть файл

@ -18,6 +18,9 @@ body contains bdb10cf
body !contains UA-
GET https://golang.org/cmd/compile/internal/amd64/
redirect == https://pkg.go.dev/cmd/compile/internal/amd64
GET https://golang.org/cmd/compile/internal/amd64/?m=old
body contains href="/src/cmd/compile/internal/amd64/ssa.go"
GET https://golang.org/conduct
@ -74,57 +77,94 @@ redirect == /help
GET https://golang.org/help
body contains Get help
GET https://golang.org/pkg/fmt/
body contains Package fmt implements formatted I/O
GET https://golang.org/src/fmt/
body contains scan_test.go
GET https://golang.org/src/fmt/print.go
body contains // Println formats using
GET https://golang.org/pkg/fmt/
redirect == https://pkg.go.dev/fmt
GET https://golang.org/pkg/fmt/?m=old
body contains Package fmt implements formatted I/O
GET https://golang.google.cn/pkg/fmt/
body contains Package fmt implements formatted I/O
GET https://golang.org/pkg
redirect == /pkg/
GET https://golang.org/pkg/
redirect == https://pkg.go.dev/std
GET https://tip.golang.org/pkg/
redirect == https://pkg.go.dev/std@master
GET https://golang.org/pkg?m=old
redirect == /pkg/?m=old
GET https://golang.org/pkg/?m=old
body contains Standard library
body contains Package fmt implements formatted I/O
body !contains internal/syscall
body !contains cmd/gc
GET https://golang.org/pkg/?m=all
GET https://golang.org/pkg/?m=old,all
body contains Standard library
body contains Package fmt implements formatted I/O
body contains internal/syscall/?m=all
body !contains cmd/gc
GET https://golang.org/pkg/bufio/
body contains href="/pkg/io/#Writer
redirect == https://pkg.go.dev/bufio
GET https://golang.org/pkg/bufio/?GOOS=windows&GOARCH=amd64
redirect == https://pkg.go.dev/bufio?GOOS=windows&GOARCH=amd64
GET https://tip.golang.org/pkg/bufio/
redirect == https://pkg.go.dev/bufio@master
GET https://golang.org/pkg/bufio/?m=old
body contains href="/pkg/io/?m=old#Writer
body !contains href="/pkg/io/#Writer
GET https://golang.org/pkg/database/sql/
redirect == https://pkg.go.dev/database/sql
GET https://golang.org/pkg/database/sql/?m=old
body contains The number of connections currently in use; added in Go 1.11
body contains The number of idle connections; added in Go 1.11
GET https://golang.org/cmd/compile/internal/amd64/
body contains href="/src/cmd/compile/internal/amd64/ssa.go"
GET https://golang.org/pkg/math/bits/
redirect == https://pkg.go.dev/math/bits
GET https://golang.org/pkg/math/bits/?m=old
body contains Added in Go 1.9
GET https://golang.org/pkg/net/
redirect == https://pkg.go.dev/net
GET https://golang.org/pkg/net/?m=old
body contains // IPv6 scoped addressing zone; added in Go 1.1
GET https://golang.org/pkg/net/http/
GET https://golang.org/pkg/net/http/?m=old
body contains title="Added in Go 1.11"
GET https://golang.org/pkg/net/http/httptrace/
redirect == https://pkg.go.dev/net/http/httptrace
GET https://golang.org/pkg/net/http/httptrace/?m=old
body ~ Got1xxResponse.*// Go 1\.11
body ~ GotFirstResponseByte func\(\)\s*$
GET https://golang.org/pkg/os/
GET https://golang.org/pkg/os/?m=old
body contains func Open
GET https://golang.org/pkg/strings/
redirect == https://pkg.go.dev/strings
GET https://golang.org/pkg/strings/?m=old
body contains href="/src/strings/strings.go"
GET https://golang.org/project

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

@ -70,6 +70,7 @@ const (
ModeAll Mode = 1 << iota // do not filter exports
ModeFlat // show directory in a flat (non-indented) manner
ModeMethods // show all embedded methods
ModeOld // do not redirect to pkg.go.dev
ModeBuiltin // don't associate consts, vars, and factory functions with types (not exposed via ?m= query parameter, used for package builtin, see issue 6645)
)
@ -79,6 +80,7 @@ var modeNames = []string{
"all",
"flat",
"methods",
"old",
}
// generate a query string for persisting PageInfoMode between pages.

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

@ -20,16 +20,17 @@ import (
type goLink struct {
path, name string // package path, identifier name
isVal bool // identifier is defined in a const or var declaration
oldDocs bool // link to ?m=old docs
}
func (l *goLink) tags() (start, end string) {
switch {
case l.path != "" && l.name == "":
// package path
return `<a href="/pkg/` + l.path + `/">`, `</a>`
return `<a href="/pkg/` + l.path + `/` + l.docSuffix() + `">`, `</a>`
case l.path != "" && l.name != "":
// qualified identifier
return `<a href="/pkg/` + l.path + `/#` + l.name + `">`, `</a>`
return `<a href="/pkg/` + l.path + `/` + l.docSuffix() + `#` + l.name + `">`, `</a>`
case l.path == "" && l.name != "":
// local identifier
if l.isVal {
@ -42,6 +43,13 @@ func (l *goLink) tags() (start, end string) {
return "", ""
}
func (l *goLink) docSuffix() string {
if l.oldDocs {
return "?m=old"
}
return ""
}
// goLinksFor returns the list of links for the identifiers used
// by node in the same order as they appear in the source.
func goLinksFor(node ast.Node) (links []goLink) {

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

@ -37,6 +37,7 @@ type Config struct {
Highlight string // highlight matches for this regexp with <span class="highlight">
Selection Selection // mark selected spans with <span class="selection">
AST ast.Node // link uses to declarations, assuming text is formatting of AST
OldDocs bool // emit links to ?m=old docs
}
// Format formats text to HTML according to the configuration cfg.
@ -55,6 +56,11 @@ func Format(text []byte, cfg Config) (html []byte) {
if cfg.AST != nil {
idents = tokenSelection(text, token.IDENT)
goLinks = goLinksFor(cfg.AST)
if cfg.OldDocs {
for i := range goLinks {
goLinks[i].oldDocs = true
}
}
}
formatSelections(&buf, text, goLinks, comments, highlights, cfg.Selection, idents)

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

@ -36,6 +36,7 @@ func (p *Page) Node(node interface{}) template.HTML {
buf2.Write(texthtml.Format(buf1.Bytes(), texthtml.Config{
AST: n,
GoComments: true,
OldDocs: p.OldDocs,
}))
return template.HTML(buf2.String())
}
@ -50,6 +51,7 @@ func (p *Page) NodeTOC(node interface{}) template.HTML {
var buf2 bytes.Buffer
buf2.Write(texthtml.Format(buf1.Bytes(), texthtml.Config{
GoComments: true,
OldDocs: p.OldDocs,
}))
return sanitize(template.HTML(buf2.String()))

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

@ -7,6 +7,7 @@ package web
import (
"log"
"net/http"
"net/url"
"path"
"strings"
@ -29,6 +30,36 @@ func (h *docServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
relpath = strings.TrimPrefix(relpath, "/")
mode := pkgdoc.ParseMode(r.FormValue("m"))
// Redirect to pkg.go.dev.
// We provide two overrides for the redirect.
// First, the request can set ?m=old to get the old pages.
// Second, the request can come from China:
// since pkg.go.dev is not available in China, we serve the docs directly.
if mode&pkgdoc.ModeOld == 0 && !GoogleCN(r) {
if relpath == "" {
relpath = "std"
}
suffix := ""
if r.Host == "tip.golang.org" {
suffix = "@master"
}
if goos, goarch := r.FormValue("GOOS"), r.FormValue("GOARCH"); goos != "" || goarch != "" {
suffix += "?"
if goos != "" {
suffix += "GOOS=" + url.QueryEscape(goos)
}
if goarch != "" {
if goos != "" {
suffix += "&"
}
suffix += "GOARCH=" + url.QueryEscape(goarch)
}
}
http.Redirect(w, r, "https://pkg.go.dev/"+relpath+suffix, http.StatusTemporaryRedirect)
return
}
if relpath == "builtin" {
// The fake built-in package contains unexported identifiers,
// but we want to show them. Also, disable type association,
@ -81,6 +112,7 @@ func (h *docServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Subtitle: subtitle,
Template: name,
Data: info,
OldDocs: mode&pkgdoc.ModeOld != 0,
})
}

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

@ -117,6 +117,9 @@ type Page struct {
Template string // template to apply to data (empty string when Data is raw template.HTML)
Data interface{} // data to be rendered into page frame
// Filled in for document rendering
OldDocs bool // use ?m=old in doc links
// Filled in automatically by ServePage
GoogleCN bool // served on golang.google.cn
GoogleAnalytics string // Google Analytics tag