blob: d8fd23c9d0f1a9b9902ba7874138c2fd0957a9f9 [file] [log] [blame]
// Copyright 2020 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.
package middleware
import (
"net/http"
"net/url"
"strings"
"golang.org/x/mod/module"
)
const (
goGithubRepoURLPath = "/github.com/golang/go"
pkgGoDevHost = "pkg.go.dev"
)
// GodocOrgRedirect redirects requests from godoc.org to pkg.go.dev.
func GodocOrgRedirect() Middleware {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !strings.HasSuffix(r.Host, "godoc.org") {
h.ServeHTTP(w, r)
return
}
http.Redirect(w, r, pkgGoDevURL(r.URL).String(), http.StatusMovedPermanently)
})
}
}
func pkgGoDevURL(godocURL *url.URL) *url.URL {
u := &url.URL{Scheme: "https", Host: pkgGoDevHost}
q := url.Values{"utm_source": []string{"godoc"}}
if strings.Contains(godocURL.Path, "/vendor/") || strings.HasSuffix(godocURL.Path, "/vendor") {
u.Path = "/"
u.RawQuery = q.Encode()
return u
}
if strings.HasPrefix(godocURL.Path, goGithubRepoURLPath) ||
strings.HasPrefix(godocURL.Path, goGithubRepoURLPath+"/src") {
u.Path = strings.TrimPrefix(strings.TrimPrefix(godocURL.Path, goGithubRepoURLPath), "/src")
if u.Path == "" {
u.Path = "/std"
}
u.RawQuery = q.Encode()
return u
}
_, isSVG := godocURL.Query()["status.svg"]
_, isPNG := godocURL.Query()["status.png"]
if isSVG || isPNG {
u.Path = "/badge" + godocURL.Path
u.RawQuery = q.Encode()
return u
}
switch godocURL.Path {
case "/-/go":
u.Path = "/std"
case "/-/about":
u.Path = "/about"
case "/C":
u.Path = "/C"
case "/":
if qparam := godocURL.Query().Get("q"); qparam != "" {
u.Path = "/search"
q.Set("q", qparam)
} else {
u.Path = "/"
}
case "":
u.Path = ""
case "/-/subrepo":
u.Path = "/search"
q.Set("q", "golang.org/x")
default:
{
godocURL.Path = strings.TrimSuffix(godocURL.Path, "/")
// If the import path is invalid, redirect to
// https://golang.org/issue/43036, so that the users has more context
// on why this path does not work on pkg.go.dev.
if err := module.CheckImportPath(strings.TrimPrefix(godocURL.Path, "/")); err != nil && strings.Contains(err.Error(), "invalid char") {
u.Host = "golang.org"
u.Path = "/issue/43036"
return u
}
u.Path = godocURL.Path
if _, ok := godocURL.Query()["imports"]; ok {
q.Set("tab", "imports")
} else if _, ok := godocURL.Query()["importers"]; ok {
q.Set("tab", "importedby")
}
}
}
u.RawQuery = q.Encode()
return u
}