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