func serveHome(resp web.Response, req *web.Request) error { q := strings.TrimSpace(req.Form.Get("q")) if q == "" { return executeTemplate(resp, "home"+templateExt(req), web.StatusOK, map[string]interface{}{"freq": freq.Get(), "recent": recent.Get()}) } if path, ok := isBrowseURL(q); ok { q = path } if doc.IsValidRemotePath(q) { pdoc, pkgs, err := getDoc(q, queryRequest) if err == nil && (pdoc != nil || len(pkgs) > 0) { return web.Redirect(resp, req, "/"+q, 302, nil) } } pkgs, err := db.Query(q) if err != nil { return err } return executeTemplate(resp, "results"+templateExt(req), 200, map[string]interface{}{"q": q, "pkgs": pkgs}) }
func serveRefresh(resp web.Response, req *web.Request) error { path := req.Form.Get("path") _, pkgs, _, err := db.Get(path) if err != nil { return err } c := make(chan error, 1) go func() { _, err := crawlDoc("rfrsh", path, nil, len(pkgs) > 0) c <- err }() select { case err = <-c: case <-time.After(*getTimeout): err = errUpdateTimeout } if err != nil { return err } return web.Redirect(resp, req, "/"+path, 302, nil) }
func servePresentation(resp web.Response, req *web.Request) error { if p := path.Clean(req.URL.Path); p != req.URL.Path { return web.Redirect(resp, req, p, 301, nil) } presMu.Lock() for p, pres := range presentations { if time.Since(pres.Updated) > 15*time.Minute { delete(presentations, p) } } p := req.RouteVars["path"] pres := presentations[p] presMu.Unlock() if pres == nil { var err error log.Println("Fetch presentation ", p) pres, err = doc.GetPresentation(httpClient, p) if err != nil { return err } presMu.Lock() presentations[p] = pres presMu.Unlock() } ctx := &present.Context{ ReadFile: func(name string) ([]byte, error) { if p, ok := pres.Files[name]; ok { return p, nil } return nil, fmt.Errorf("pres file not found %s", name) }, } doc, err := ctx.Parse(bytes.NewReader(pres.Files[pres.Filename]), pres.Filename, 0) if err != nil { return err } return renderPresentation(resp, p, doc) }
func servePackage(resp web.Response, req *web.Request) error { p := path.Clean(req.URL.Path) if p != req.URL.Path { return web.Redirect(resp, req, p, 301, nil) } requestType := humanRequest if isRobot(req) { requestType = robotRequest } path := req.RouteVars["path"] pdoc, pkgs, err := getDoc(path, requestType) if err != nil { return err } if (pdoc == nil || pdoc.Name == "") && len(pkgs) == 0 { return &web.Error{Status: web.StatusNotFound} } if pdoc == nil { pdocChild, _, _, err := db.Get(pkgs[0].Path) if err != nil { return err } pdoc = &doc.Package{ ProjectName: pdocChild.ProjectName, ProjectRoot: pdocChild.ProjectRoot, ProjectURL: pdocChild.ProjectURL, ImportPath: path, } } if requestType != robotRequest { freq.Add(path) recent.Add(path) } switch req.Form.Get("view") { case "imports": if pdoc.Name == "" { return &web.Error{Status: web.StatusNotFound} } pkgs, err = db.Imports(pdoc) if err != nil { return err } return executeTemplate(resp, "imports.html", web.StatusOK, map[string]interface{}{ "pkgs": pkgs, "pdoc": pdoc, }) case "importGraph": if pdoc.Name == "" { return &web.Error{Status: web.StatusNotFound} } nodes, edges, err := db.ImportGraph(pdoc) if err != nil { return err } return executeTemplate(resp, "graph.html", web.StatusOK, map[string]interface{}{ "nodes": nodes, "edges": edges, "pdoc": pdoc, }) case "importers": if pdoc.Name == "" { return &web.Error{Status: web.StatusNotFound} } pkgs, err = db.Importers(path) if err != nil { return err } return executeTemplate(resp, "importers.html", web.StatusOK, map[string]interface{}{ "pkgs": pkgs, "pdoc": pdoc, }) case "": importerCount, err := db.ImporterCount(path) if err != nil { return err } template := "pkg" if pdoc.IsCmd { template = "cmd" } template += templateExt(req) return executeTemplate(resp, template, 200, map[string]interface{}{ "pkgs": pkgs, "pdoc": pdoc, "importerCount": importerCount, }) } return &web.Error{Status: web.StatusNotFound} }
func servePackage(resp web.Response, req *web.Request) error { p := path.Clean(req.URL.Path) if strings.HasPrefix(p, "/pkg/") { p = p[len("/pkg"):] } if p != req.URL.Path { return web.Redirect(resp, req, p, 301, nil) } requestType := humanRequest if isRobot(req) { requestType = robotRequest } path := req.RouteVars["path"] pdoc, pkgs, err := getDoc(path, requestType) if err != nil { return err } if pdoc == nil { if len(pkgs) == 0 { return &web.Error{Status: web.StatusNotFound} } pdocChild, _, _, err := db.Get(pkgs[0].Path) if err != nil { return err } pdoc = &doc.Package{ ProjectName: pdocChild.ProjectName, ProjectRoot: pdocChild.ProjectRoot, ProjectURL: pdocChild.ProjectURL, ImportPath: path, } } switch { case len(req.Form) == 0: if requestType == humanRequest && pdoc.Name != "" && // not a directory pdoc.ProjectRoot != "" && // not a standard package !pdoc.IsCmd && len(pdoc.Errors) == 0 && !popularLinkReferral(req) { if err := db.IncrementPopularScore(pdoc.ImportPath); err != nil { log.Print("ERROR db.IncrementPopularScore(%s): %v", pdoc.ImportPath, err) } } importerCount, err := db.ImporterCount(path) if err != nil { return err } template := "pkg" if pdoc.IsCmd { template = "cmd" } template += templateExt(req) return executeTemplate(resp, template, web.StatusOK, nil, map[string]interface{}{ "pkgs": pkgs, "pdoc": pdoc, "importerCount": importerCount, }) case hasFormValue(req, "imports"): if pdoc.Name == "" { break } pkgs, err = db.Packages(pdoc.Imports) if err != nil { return err } return executeTemplate(resp, "imports.html", web.StatusOK, nil, map[string]interface{}{ "pkgs": pkgs, "pdoc": pdoc, }) case hasFormValue(req, "importers"): if pdoc.Name == "" { break } pkgs, err = db.Importers(path) if err != nil { return err } return executeTemplate(resp, "importers.html", web.StatusOK, nil, map[string]interface{}{ "pkgs": pkgs, "pdoc": pdoc, }) case hasFormValue(req, "import-graph"): if pdoc.Name == "" { break } hide := req.Form.Get("hide") == "1" pkgs, edges, err := db.ImportGraph(pdoc, hide) if err != nil { return err } b, err := renderGraph(pdoc, pkgs, edges) if err != nil { return err } return executeTemplate(resp, "graph.html", web.StatusOK, nil, map[string]interface{}{ "svg": template.HTML(b), "pdoc": pdoc, "hide": hide, }) case req.Form.Get("play") != "": u, err := playURL(pdoc, req.Form.Get("play"), req.Form.Get("name")) if err != nil { return err } return web.Redirect(resp, req, u, 301, nil) case req.Form.Get("view") != "": // Redirect deprecated view= queries. var q string switch view := req.Form.Get("view"); view { case "imports", "importers": q = view case "import-graph": if req.Form.Get("hide") == "1" { q = "import-graph&hide=1" } else { q = "import-graph" } } if q != "" { u := *req.URL u.RawQuery = q return web.Redirect(resp, req, u.String(), 301, nil) } } return &web.Error{Status: web.StatusNotFound} }
func main() { flag.Parse() log.Printf("Starting server, os.Args=%s", strings.Join(os.Args, " ")) if err := readSecrets(); err != nil { log.Fatal(err) } if *srcZip != "" { r, err := zip.OpenReader(*srcZip) if err != nil { log.Fatal(err) } for _, f := range r.File { if strings.HasPrefix(f.Name, "root/") { srcFiles[f.Name[len("root/"):]] = f } } } 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"}, {"imports.html", "common.html", "layout.html"}, {"file.html", "common.html", "layout.html"}, {"index.html", "common.html", "layout.html"}, {"notfound.html", "common.html", "layout.html"}, {"pkg.html", "common.html", "layout.html"}, {"results.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"}, {"opensearch.xml"}, }); err != nil { log.Fatal(err) } if err := parsePresentTemplates([][]string{ {".article", "article.tmpl", "action.tmpl"}, {".slide", "slides.tmpl", "action.tmpl"}, }); err != nil { log.Fatal(err) } present.PlayEnabled = true var err error db, err = database.New() if err != nil { log.Fatal(err) } go runBackgroundTasks() staticConfig := &web.StaticConfig{ Header: web.Header{web.HeaderCacheControl: {"public, max-age=3600"}}, Directory: *assetsDir, GzDirectory: *gzAssetsDir, } presentStaticConfig := &web.StaticConfig{ Header: web.Header{web.HeaderCacheControl: {"public, max-age=3600"}}, Directory: *presentDir, } h := web.NewHostRouter() r := web.NewRouter() r.Add("/").GetFunc(servePresentHome) r.Add("/compile").PostFunc(serveCompile) r.Add("/favicon.ico").Get(staticConfig.FileHandler("favicon.ico")) r.Add("/google3d2f3cd4cc2bb44b.html").Get(staticConfig.FileHandler("google3d2f3cd4cc2bb44b.html")) r.Add("/humans.txt").Get(staticConfig.FileHandler("humans.txt")) r.Add("/play.js").Get(dataHandler("play.js", "text/javascript", *presentDir, "js/jquery.js", "js/playground.js", "js/play.js")) r.Add("/robots.txt").Get(staticConfig.FileHandler("presentRobots.txt")) r.Add("/static/<path:.*>").Get(presentStaticConfig.DirectoryHandler("static")) if *redirGoTalks { r.Add("/code.google.com/p/go.talks/<path:.+>").GetFunc(func(resp web.Response, req *web.Request) error { return web.Redirect(resp, req, "http://talks.golang.org/"+req.RouteVars["path"], 301, nil) }) } r.Add("/<path:.+>").GetFunc(servePresentation) h.Add("talks.<:.*>", web.ErrorHandler(handlePresentError, web.FormAndCookieHandler(6000, false, r))) r = web.NewRouter() r.Add("/favicon.ico").Get(staticConfig.FileHandler("favicon.ico")) r.Add("/google3d2f3cd4cc2bb44b.html").Get(staticConfig.FileHandler("google3d2f3cd4cc2bb44b.html")) r.Add("/humans.txt").Get(staticConfig.FileHandler("humans.txt")) r.Add("/robots.txt").Get(staticConfig.FileHandler("presentRobots.txt")) r.Add("/search").GetFunc(serveAPISearch) r.Add("/packages").GetFunc(serveAPIPackages) r.Add("/importers/<path:.+>").GetFunc(serveAPIImporters) h.Add("api.<:.*>", web.ErrorHandler(handleAPIError, web.FormAndCookieHandler(6000, false, r))) r = web.NewRouter() r.Add("/-/site.js").Get(dataHandler("site.js", "text/javascript", *assetsDir, "third_party/jquery.timeago.js", "third_party/typeahead.min.js", "third_party/bootstrap/js/bootstrap.min.js", "site.js")) r.Add("/-/site.css").Get(dataHandler("site.css", "text/css", *assetsDir, "third_party/bootstrap/css/bootstrap.min.css", "site.css")) r.Add("/").GetFunc(serveHome) r.Add("/-/about").GetFunc(serveAbout) r.Add("/-/bot").GetFunc(serveBot) r.Add("/-/opensearch.xml").GetFunc(serveOpenSearchDescription) r.Add("/-/typeahead").GetFunc(serveTypeahead) r.Add("/-/go").GetFunc(serveGoIndex) r.Add("/-/subrepo").GetFunc(serveGoSubrepoIndex) r.Add("/-/index").GetFunc(serveIndex) r.Add("/-/refresh").PostFunc(serveRefresh) r.Add("/-/static/<path:.*>").Get(staticConfig.DirectoryHandler("static")) r.Add("/a/index").Get(web.RedirectHandler("/-/index", 301)) r.Add("/about").Get(web.RedirectHandler("/-/about", 301)) r.Add("/favicon.ico").Get(staticConfig.FileHandler("favicon.ico")) r.Add("/google3d2f3cd4cc2bb44b.html").Get(staticConfig.FileHandler("google3d2f3cd4cc2bb44b.html")) r.Add("/humans.txt").Get(staticConfig.FileHandler("humans.txt")) r.Add("/robots.txt").Get(staticConfig.FileHandler("robots.txt")) r.Add("/BingSiteAuth.xml").Get(staticConfig.FileHandler("BingSiteAuth.xml")) r.Add("/C").Get(web.RedirectHandler("http://golang.org/doc/articles/c_go_cgo.html", 301)) r.Add("/<path:.+>").GetFunc(servePackage) h.Add("<:.*>", web.ErrorHandler(handleError, web.FormAndCookieHandler(1000, false, r))) listener, err := net.Listen("tcp", *httpAddr) if err != nil { log.Fatal("Listen", err) return } defer listener.Close() s := &server.Server{Listener: listener, Handler: h} // add logger err = s.Serve() if err != nil { log.Fatal("Server", err) } }
func servePackage(resp web.Response, req *web.Request) error { p := path.Clean(req.URL.Path) if strings.HasPrefix(p, "/pkg/") { p = p[len("/pkg"):] } if p != req.URL.Path { return web.Redirect(resp, req, p, 301, nil) } requestType := humanRequest if isRobot(req) { requestType = robotRequest } importPath := req.RouteVars["path"] pdoc, pkgs, err := getDoc(importPath, requestType) if err != nil { return err } if pdoc == nil { if len(pkgs) == 0 { return &web.Error{Status: web.StatusNotFound} } pdocChild, _, _, err := db.Get(pkgs[0].Path) if err != nil { return err } pdoc = &doc.Package{ ProjectName: pdocChild.ProjectName, ProjectRoot: pdocChild.ProjectRoot, ProjectURL: pdocChild.ProjectURL, ImportPath: importPath, } } switch { case len(req.Form) == 0: if requestType == humanRequest && pdoc.Name != "" && // not a directory pdoc.ProjectRoot != "" && // not a standard package !pdoc.IsCmd && len(pdoc.Errors) == 0 && !popularLinkReferral(req) { if err := db.IncrementPopularScore(pdoc.ImportPath); err != nil { log.Print("ERROR db.IncrementPopularScore(%s): %v", pdoc.ImportPath, err) } } importerCount, err := db.ImporterCount(importPath) if err != nil { return err } template := "dir" switch { case pdoc.IsCmd: template = "cmd" case pdoc.Name != "": template = "pkg" } template += templateExt(req) if srcFiles[importPath+"/_sourceMap"] != nil { for _, f := range pdoc.Files { if srcFiles[importPath+"/"+f.Name] != nil { f.URL = fmt.Sprintf("/%s?file=%s", importPath, f.Name) pdoc.LineFmt = "%s#L%d" } } } return executeTemplate(resp, template, web.StatusOK, nil, map[string]interface{}{ "pkgs": pkgs, "pdoc": newTDoc(pdoc), "importerCount": importerCount, }) case isView(req, "imports"): if pdoc.Name == "" { break } pkgs, err = db.Packages(pdoc.Imports) if err != nil { return err } return executeTemplate(resp, "imports.html", web.StatusOK, nil, map[string]interface{}{ "pkgs": pkgs, "pdoc": newTDoc(pdoc), }) case isView(req, "redir"): if srcFiles == nil { break } f := srcFiles[importPath+"/_sourceMap"] if f == nil { break } r, err := f.Open() if err != nil { return err } defer r.Close() var sourceMap map[string]string if err := gob.NewDecoder(r).Decode(&sourceMap); err != nil { return err } id := req.Form.Get("redir") fname := sourceMap[id] if fname == "" { break } return web.Redirect(resp, req, fmt.Sprintf("?file=%s#%s", fname, id), 301, nil) case isView(req, "file"): if srcFiles == nil { break } fname := req.Form.Get("file") f := srcFiles[importPath+"/"+fname] if f == nil { break } r, err := f.Open() if err != nil { return err } defer r.Close() src := make([]byte, f.UncompressedSize64) if n, err := io.ReadFull(r, src); err != nil { return err } else { src = src[:n] } var url string for _, f := range pdoc.Files { if f.Name == fname { url = f.URL } } return executeTemplate(resp, "file.html", web.StatusOK, nil, map[string]interface{}{ "fname": fname, "url": url, "src": template.HTML(src), "pdoc": newTDoc(pdoc), }) case isView(req, "importers"): if pdoc.Name == "" { break } pkgs, err = db.Importers(importPath) if err != nil { return err } return executeTemplate(resp, "importers.html", web.StatusOK, nil, map[string]interface{}{ "pkgs": pkgs, "pdoc": newTDoc(pdoc), }) case isView(req, "import-graph"): if pdoc.Name == "" { break } hide := req.Form.Get("hide") == "1" pkgs, edges, err := db.ImportGraph(pdoc, hide) if err != nil { return err } b, err := renderGraph(pdoc, pkgs, edges) if err != nil { return err } return executeTemplate(resp, "graph.html", web.StatusOK, nil, map[string]interface{}{ "svg": template.HTML(b), "pdoc": newTDoc(pdoc), "hide": hide, }) case isView(req, "play"): u, err := playURL(pdoc, req.Form.Get("play")) if err != nil { return err } return web.Redirect(resp, req, u, 301, nil) case req.Form.Get("view") != "": // Redirect deprecated view= queries. var q string switch view := req.Form.Get("view"); view { case "imports", "importers": q = view case "import-graph": if req.Form.Get("hide") == "1" { q = "import-graph&hide=1" } else { q = "import-graph" } } if q != "" { u := *req.URL u.RawQuery = q return web.Redirect(resp, req, u.String(), 301, nil) } } return &web.Error{Status: web.StatusNotFound} }
func servePackage(resp web.Response, req *web.Request) error { if p := path.Clean(req.URL.Path); p != req.URL.Path { return web.Redirect(resp, req, p, 301, nil) } requestType := humanRequest if isRobot(req) { requestType = robotRequest } path := req.RouteVars["path"] pdoc, pkgs, err := getDoc(path, requestType) if err != nil { return err } if pdoc == nil { if len(pkgs) == 0 { return &web.Error{Status: web.StatusNotFound} } pdocChild, _, _, err := db.Get(pkgs[0].Path) if err != nil { return err } pdoc = &doc.Package{ ProjectName: pdocChild.ProjectName, ProjectRoot: pdocChild.ProjectRoot, ProjectURL: pdocChild.ProjectURL, ImportPath: path, } } switch req.Form.Get("view") { case "imports": if pdoc.Name == "" { break } pkgs, err = db.Packages(pdoc.Imports) if err != nil { return err } return executeTemplate(resp, "imports.html", web.StatusOK, map[string]interface{}{ "pkgs": pkgs, "pdoc": pdoc, }) case "importers": if pdoc.Name == "" { break } pkgs, err = db.Importers(path) if err != nil { return err } return executeTemplate(resp, "importers.html", web.StatusOK, map[string]interface{}{ "pkgs": pkgs, "pdoc": pdoc, }) case "import-graph": if pdoc.Name == "" { break } hide := req.Form.Get("hide") == "1" pkgs, edges, err := db.ImportGraph(pdoc, hide) if err != nil { return err } b, err := renderGraph(pdoc, pkgs, edges) if err != nil { return err } return executeTemplate(resp, "graph.html", web.StatusOK, map[string]interface{}{ "svg": template.HTML(b), "pdoc": pdoc, "hide": hide, }) case "": importerCount, err := db.ImporterCount(path) if err != nil { return err } template := "pkg" if pdoc.IsCmd { template = "cmd" } template += templateExt(req) return executeTemplate(resp, template, web.StatusOK, map[string]interface{}{ "pkgs": pkgs, "pdoc": pdoc, "importerCount": importerCount, }) } return &web.Error{Status: web.StatusNotFound} }