Пример #1
0
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})
}
Пример #2
0
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)
}
Пример #3
0
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)
}
Пример #4
0
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}
}
Пример #5
0
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}
}
Пример #6
0
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)
	}
}
Пример #7
0
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}
}
Пример #8
0
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}
}