gddo-server: consolidate template initialization

This is in preparation for passing around the template map explicitly
instead of using it as a global.  It also moves the manifest of template
sets into templates.go and out of main.go.

Change-Id: Ic7db8d5ab0186c1f4eb2446871e2c18ae1554d82
Reviewed-on: https://go-review.googlesource.com/67051
Reviewed-by: Tuo Shan <shantuo@google.com>
This commit is contained in:
Ross Light 2017-09-28 08:37:26 -07:00
Родитель ddb3324051
Коммит d0b0199669
2 изменённых файлов: 101 добавлений и 96 удалений

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

@ -310,10 +310,10 @@ func servePackage(resp http.ResponseWriter, req *http.Request) error {
}
template += templateExt(req)
return executeTemplate(resp, template, status, http.Header{"Etag": {etag}}, map[string]interface{}{
return templates.execute(resp, template, status, http.Header{"Etag": {etag}}, map[string]interface{}{
"flashMessages": flashMessages,
"pkgs": pkgs,
"pdoc": newTDoc(pdoc),
"pdoc": newTDoc(viper.GetViper(), pdoc),
"importerCount": importerCount,
})
case isView(req, "imports"):
@ -324,20 +324,20 @@ func servePackage(resp http.ResponseWriter, req *http.Request) error {
if err != nil {
return err
}
return executeTemplate(resp, "imports.html", http.StatusOK, nil, map[string]interface{}{
return templates.execute(resp, "imports.html", http.StatusOK, nil, map[string]interface{}{
"flashMessages": flashMessages,
"pkgs": pkgs,
"pdoc": newTDoc(pdoc),
"pdoc": newTDoc(viper.GetViper(), pdoc),
})
case isView(req, "tools"):
proto := "http"
if req.Host == "godoc.org" {
proto = "https"
}
return executeTemplate(resp, "tools.html", http.StatusOK, nil, map[string]interface{}{
return templates.execute(resp, "tools.html", http.StatusOK, nil, map[string]interface{}{
"flashMessages": flashMessages,
"uri": fmt.Sprintf("%s://%s/%s", proto, req.Host, importPath),
"pdoc": newTDoc(pdoc),
"pdoc": newTDoc(viper.GetViper(), pdoc),
})
case isView(req, "importers"):
if pdoc.Name == "" {
@ -352,10 +352,10 @@ func servePackage(resp http.ResponseWriter, req *http.Request) error {
// Hide back links from robots.
template = "importers_robot.html"
}
return executeTemplate(resp, template, http.StatusOK, nil, map[string]interface{}{
return templates.execute(resp, template, http.StatusOK, nil, map[string]interface{}{
"flashMessages": flashMessages,
"pkgs": pkgs,
"pdoc": newTDoc(pdoc),
"pdoc": newTDoc(viper.GetViper(), pdoc),
})
case isView(req, "import-graph"):
if requestType == robotRequest {
@ -379,10 +379,10 @@ func servePackage(resp http.ResponseWriter, req *http.Request) error {
if err != nil {
return err
}
return executeTemplate(resp, "graph.html", http.StatusOK, nil, map[string]interface{}{
return templates.execute(resp, "graph.html", http.StatusOK, nil, map[string]interface{}{
"flashMessages": flashMessages,
"svg": template.HTML(b),
"pdoc": newTDoc(pdoc),
"pdoc": newTDoc(viper.GetViper(), pdoc),
"hide": hide,
})
case isView(req, "play"):
@ -447,7 +447,7 @@ func serveGoIndex(resp http.ResponseWriter, req *http.Request) error {
if err != nil {
return err
}
return executeTemplate(resp, "std.html", http.StatusOK, nil, map[string]interface{}{
return templates.execute(resp, "std.html", http.StatusOK, nil, map[string]interface{}{
"pkgs": pkgs,
})
}
@ -457,7 +457,7 @@ func serveGoSubrepoIndex(resp http.ResponseWriter, req *http.Request) error {
if err != nil {
return err
}
return executeTemplate(resp, "subrepo.html", http.StatusOK, nil, map[string]interface{}{
return templates.execute(resp, "subrepo.html", http.StatusOK, nil, map[string]interface{}{
"pkgs": pkgs,
})
}
@ -540,7 +540,7 @@ func serveHome(resp http.ResponseWriter, req *http.Request) error {
return err
}
return executeTemplate(resp, "home"+templateExt(req), http.StatusOK, nil,
return templates.execute(resp, "home"+templateExt(req), http.StatusOK, nil,
map[string]interface{}{"Popular": pkgs})
}
@ -573,17 +573,17 @@ func serveHome(resp http.ResponseWriter, req *http.Request) error {
gceLogger.LogEvent(resp, req, logPkgs)
}
return executeTemplate(resp, "results"+templateExt(req), http.StatusOK, nil,
return templates.execute(resp, "results"+templateExt(req), http.StatusOK, nil,
map[string]interface{}{"q": q, "pkgs": pkgs})
}
func serveAbout(resp http.ResponseWriter, req *http.Request) error {
return executeTemplate(resp, "about.html", http.StatusOK, nil,
return templates.execute(resp, "about.html", http.StatusOK, nil,
map[string]interface{}{"Host": req.Host})
}
func serveBot(resp http.ResponseWriter, req *http.Request) error {
return executeTemplate(resp, "bot.html", http.StatusOK, nil, nil)
return templates.execute(resp, "bot.html", http.StatusOK, nil, nil)
}
func serveHealthCheck(resp http.ResponseWriter, req *http.Request) {
@ -757,7 +757,7 @@ func errorText(err error) string {
func handleError(resp http.ResponseWriter, req *http.Request, status int, err error) {
switch status {
case http.StatusNotFound:
executeTemplate(resp, "notfound"+templateExt(req), status, nil, map[string]interface{}{
templates.execute(resp, "notfound"+templateExt(req), status, nil, map[string]interface{}{
"flashMessages": getFlashMessages(resp, req),
})
default:
@ -846,38 +846,12 @@ func main() {
doc.SetDefaultGOOS(viper.GetString(ConfigDefaultGOOS))
httpClient = newHTTPClient(viper.GetViper())
if err := parseHTMLTemplates([][]string{
{"about.html", "common.html", "layout.html"},
{"bot.html", "common.html", "layout.html"},
{"cmd.html", "common.html", "layout.html"},
{"dir.html", "common.html", "layout.html"},
{"home.html", "common.html", "layout.html"},
{"importers.html", "common.html", "layout.html"},
{"importers_robot.html", "common.html", "layout.html"},
{"imports.html", "common.html", "layout.html"},
{"notfound.html", "common.html", "layout.html"},
{"pkg.html", "common.html", "layout.html"},
{"results.html", "common.html", "layout.html"},
{"tools.html", "common.html", "layout.html"},
{"std.html", "common.html", "layout.html"},
{"subrepo.html", "common.html", "layout.html"},
{"graph.html", "common.html"},
}); err != nil {
log.Fatal(err)
}
if err := parseTextTemplates([][]string{
{"cmd.txt", "common.txt"},
{"dir.txt", "common.txt"},
{"home.txt", "common.txt"},
{"notfound.txt", "common.txt"},
{"pkg.txt", "common.txt"},
{"results.txt", "common.txt"},
}); err != nil {
log.Fatal(err)
}
var err error
templates, err = parseTemplates(viper.GetString(ConfigAssetsDir), viper.GetViper())
if err != nil {
log.Fatal(err)
}
db, err = database.New(
viper.GetString(ConfigDBServer),
viper.GetDuration(ConfigDBIdleTimeout),

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

@ -80,7 +80,8 @@ func setFlashMessages(resp http.ResponseWriter, messages []flashMessage) {
type tdoc struct {
*doc.Package
allExamples []*texample
allExamples []*texample
sourcegraphURL string
}
type texample struct {
@ -91,8 +92,11 @@ type texample struct {
obj interface{}
}
func newTDoc(pdoc *doc.Package) *tdoc {
return &tdoc{Package: pdoc}
func newTDoc(v *viper.Viper, pdoc *doc.Package) *tdoc {
return &tdoc{
Package: pdoc,
sourcegraphURL: v.GetString(ConfigSourcegraphURL),
}
}
func (pdoc *tdoc) SourceLink(pos doc.Pos, text string, textOnlyOK bool) htemp.HTML {
@ -110,7 +114,7 @@ func (pdoc *tdoc) SourceLink(pos doc.Pos, text string, textOnlyOK bool) htemp.HT
// UsesLink generates a link to uses of a symbol definition.
// title is used as the tooltip. defParts are parts of the symbol definition name.
func (pdoc *tdoc) UsesLink(title string, defParts ...string) htemp.HTML {
if viper.GetString(ConfigSourcegraphURL) == "" {
if pdoc.sourcegraphURL == "" {
return ""
}
@ -146,7 +150,7 @@ func (pdoc *tdoc) UsesLink(title string, defParts ...string) htemp.HTML {
"pkg": {pdoc.ImportPath},
"def": {def},
}
u := viper.GetString(ConfigSourcegraphURL) + "/-/godoc/refs?" + q.Encode()
u := pdoc.sourcegraphURL + "/-/godoc/refs?" + q.Encode()
return htemp.HTML(fmt.Sprintf(`<a class="uses" title="%s" href="%s">Uses</a>`, htemp.HTMLEscapeString(title), htemp.HTMLEscapeString(u)))
}
@ -485,7 +489,15 @@ var mimeTypes = map[string]string{
".txt": textMIMEType,
}
func executeTemplate(resp http.ResponseWriter, name string, status int, header http.Header, data interface{}) error {
// TODO(light): pass templates explicitly, not as a global.
var templates templateMap
type templateMap map[string]interface {
Execute(io.Writer, interface{}) error
}
func (m templateMap) execute(resp http.ResponseWriter, name string, status int, header http.Header, data interface{}) error {
for k, v := range header {
resp.Header()[k] = v
}
@ -494,7 +506,7 @@ func executeTemplate(resp http.ResponseWriter, name string, status int, header h
mimeType = textMIMEType
}
resp.Header().Set("Content-Type", mimeType)
t := templates[name]
t := m[name]
if t == nil {
return fmt.Errorf("template %s not found", name)
}
@ -505,10 +517,6 @@ func executeTemplate(resp http.ResponseWriter, name string, status int, header h
return t.Execute(resp, data)
}
var templates = map[string]interface {
Execute(io.Writer, interface{}) error
}{}
func joinTemplateDir(base string, files []string) []string {
result := make([]string, len(files))
for i := range files {
@ -517,53 +525,76 @@ func joinTemplateDir(base string, files []string) []string {
return result
}
func parseHTMLTemplates(sets [][]string) error {
for _, set := range sets {
func parseTemplates(dir string, v *viper.Viper) (templateMap, error) {
m := make(templateMap)
htmlSets := [][]string{
{"about.html", "common.html", "layout.html"},
{"bot.html", "common.html", "layout.html"},
{"cmd.html", "common.html", "layout.html"},
{"dir.html", "common.html", "layout.html"},
{"home.html", "common.html", "layout.html"},
{"importers.html", "common.html", "layout.html"},
{"importers_robot.html", "common.html", "layout.html"},
{"imports.html", "common.html", "layout.html"},
{"notfound.html", "common.html", "layout.html"},
{"pkg.html", "common.html", "layout.html"},
{"results.html", "common.html", "layout.html"},
{"tools.html", "common.html", "layout.html"},
{"std.html", "common.html", "layout.html"},
{"subrepo.html", "common.html", "layout.html"},
{"graph.html", "common.html"},
}
hfuncs := htemp.FuncMap{
"code": codeFn,
"comment": commentFn,
"equal": reflect.DeepEqual,
"gaAccount": func() string { return v.GetString(ConfigGAAccount) },
"host": hostFn,
"htmlComment": htmlCommentFn,
"importPath": importPathFn,
"isInterface": isInterfaceFn,
"isValidImportPath": gosrc.IsValidPath,
"map": mapFn,
"noteTitle": noteTitleFn,
"relativePath": relativePathFn,
"sidebarEnabled": func() bool { return v.GetBool(ConfigSidebar) },
"staticPath": func(p string) string { return cacheBusters.AppendQueryParam(p, "v") },
}
for _, set := range htmlSets {
templateName := set[0]
t := htemp.New("")
t.Funcs(htemp.FuncMap{
"code": codeFn,
"comment": commentFn,
"equal": reflect.DeepEqual,
"gaAccount": func() string { return viper.GetString(ConfigGAAccount) },
"host": hostFn,
"htmlComment": htmlCommentFn,
"importPath": importPathFn,
"isInterface": isInterfaceFn,
"isValidImportPath": gosrc.IsValidPath,
"map": mapFn,
"noteTitle": noteTitleFn,
"relativePath": relativePathFn,
"sidebarEnabled": func() bool { return viper.GetBool(ConfigSidebar) },
"staticPath": func(p string) string { return cacheBusters.AppendQueryParam(p, "v") },
"templateName": func() string { return templateName },
t := htemp.New("").Funcs(hfuncs).Funcs(htemp.FuncMap{
"templateName": func() string { return templateName },
})
if _, err := t.ParseFiles(joinTemplateDir(viper.GetString(ConfigAssetsDir), set)...); err != nil {
return err
if _, err := t.ParseFiles(joinTemplateDir(dir, set)...); err != nil {
return nil, err
}
t = t.Lookup("ROOT")
if t == nil {
return fmt.Errorf("ROOT template not found in %v", set)
return nil, fmt.Errorf("ROOT template not found in %v", set)
}
templates[set[0]] = t
m[set[0]] = t
}
return nil
}
func parseTextTemplates(sets [][]string) error {
for _, set := range sets {
t := ttemp.New("")
t.Funcs(ttemp.FuncMap{
"comment": commentTextFn,
})
if _, err := t.ParseFiles(joinTemplateDir(viper.GetString(ConfigAssetsDir), set)...); err != nil {
return err
textSets := [][]string{
{"cmd.txt", "common.txt"},
{"dir.txt", "common.txt"},
{"home.txt", "common.txt"},
{"notfound.txt", "common.txt"},
{"pkg.txt", "common.txt"},
{"results.txt", "common.txt"},
}
tfuncs := ttemp.FuncMap{
"comment": commentTextFn,
}
for _, set := range textSets {
t := ttemp.New("").Funcs(tfuncs)
if _, err := t.ParseFiles(joinTemplateDir(dir, set)...); err != nil {
return nil, err
}
t = t.Lookup("ROOT")
if t == nil {
return fmt.Errorf("ROOT template not found in %v", set)
return nil, fmt.Errorf("ROOT template not found in %v", set)
}
templates[set[0]] = t
m[set[0]] = t
}
return nil
return m, nil
}