blob: 5b3be76fc4c3e4d3f880ed299dd8c9b8948a96f5 [file] [log] [blame]
// A trivial redirector for google.golang.org.
package main
import (
"fmt"
"html/template"
"net/http"
"os"
"strings"
)
var repoMap = map[string]*repoImport{
"api": {
VCS: "git",
URL: "https://github.com/googleapis/google-api-go-client",
Src: github("googleapis/google-api-go-client"),
},
"appengine": {
VCS: "git",
URL: "https://github.com/golang/appengine",
Src: github("golang/appengine"),
},
"cloud": {
// This repo is now at "cloud.google.com/go", but still specifying the repo
// here gives nicer errors in godoc.org and the go tool.
VCS: "git",
URL: "https://github.com/googleapis/google-cloud-go",
Src: github("googleapis/google-cloud-go"),
},
"genproto": {
VCS: "git",
URL: "https://github.com/googleapis/go-genproto",
Src: github("googleapis/go-genproto"),
},
"grpc": {
VCS: "git",
URL: "https://github.com/grpc/grpc-go",
Src: github("grpc/grpc-go"),
},
"protobuf": {
VCS: "git",
URL: "https://go.googlesource.com/protobuf",
Src: github("protocolbuffers/protobuf-go"),
},
}
// repoImport represents an import meta-tag, as per
// https://golang.org/cmd/go/#hdr-Import_path_syntax
type repoImport struct {
VCS string
URL string
Src *src
}
// src represents a godoc.org source redirect.
// https://github.com/golang/gddo/search?utf8=%E2%9C%93&q=sourceMeta
type src struct {
URL string
DirTpl string
FileTpl string
}
// github returns the *src representing a github repo.
func github(base string) *src {
return &src{
URL: fmt.Sprintf("https://github.com/%s", base),
DirTpl: fmt.Sprintf("https://github.com/%s/tree/master{/dir}", base),
FileTpl: fmt.Sprintf("https://github.com/%s/tree/master{/dir}/{file}#L{line}", base),
}
}
func googsource(repo, base string) *src {
return &src{
URL: fmt.Sprintf("https://%s.googlesource.com/%s", repo, base),
DirTpl: fmt.Sprintf("https://%s.googlesource.com/%s/+/master{/dir}", repo, base),
FileTpl: fmt.Sprintf("https://%s.googlesource.com/%s/+/master{/dir}/{file}#{line}", repo, base),
}
}
func main() {
http.HandleFunc("/", handler)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
fmt.Printf("Defaulting to port %s\n", port)
}
fmt.Printf("Listening on port %s\n", port)
if err := http.ListenAndServe(fmt.Sprintf(":%s", port), nil); err != nil {
fmt.Fprintf(os.Stderr, "http.ListenAndServe: %v\n", err)
return
}
}
func handler(w http.ResponseWriter, r *http.Request) {
head, tail := strings.TrimPrefix(r.URL.Path, "/"), ""
if i := strings.Index(head, "/"); i != -1 {
head, tail = head[:i], head[i:]
}
if head == "" {
http.Redirect(w, r, "https://cloud.google.com/go/google.golang.org", http.StatusFound)
return
}
repo, ok := repoMap[head]
if !ok {
http.NotFound(w, r)
return
}
godoc := "https://godoc.org/google.golang.org/" + head + tail
// For users visting in a browser, redirect straight to godoc.org.
if isBrowser := r.FormValue("go-get") == ""; isBrowser {
http.Redirect(w, r, godoc, http.StatusFound)
return
}
data := struct {
Head, GoDoc string
Repo *repoImport
}{head, godoc, repo}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := tmpl.Execute(w, data); err != nil {
fmt.Fprintf(os.Stderr, "tmpl.Execute: %v\n", err)
}
}
var tmpl = template.Must(template.New("redir").Parse(`<!DOCTYPE html>
<html>
<head>
<meta name="go-import" content="google.golang.org/{{.Head}} {{.Repo.VCS}} {{.Repo.URL}}">
{{if .Repo.Src}}
<meta name="go-source" content="google.golang.org/{{.Head}} {{.Repo.Src.URL}} {{.Repo.Src.DirTpl}} {{.Repo.Src.FileTpl}}">
{{end}}
<meta http-equiv="refresh" content="0; url={{.GoDoc}}">
</head>
<body>
Nothing to see here. Please <a href="{{.GoDoc}}">move along</a>.
</body>
</html>
`))