func toCache(root, node, id string, content []byte, mods *service.CacheMods) error { // Write deps to filesystem. thisDep := service.CacheDep{Node: node, Cache: id} if mods != nil { for _, dep := range mods.Deps { err := appendRdeps(root, dep, []service.CacheDep{thisDep}) if err != nil { return fmt.Errorf("Could not write rdeps: %v", err) } } } // Write cache to filesystem. nodePath := filepath.Join(root, node[1:]) path := filepath.Join(nodePath, ".data", filepath.Base(id)) if err := os.MkdirAll(filepath.Dir(path), 0770); err != nil { return fmt.Errorf("Could not create node cache directory: %v", err) } if mods != nil { mods.Deps = nil } var raw bytes.Buffer enc := gob.NewEncoder(&raw) data := cacheData{Data: content, CacheMods: mods} if err := enc.Encode(&data); err != nil { return fmt.Errorf("Could not encode cache data: %v", err) } if err := ioutil.WriteFile(path, raw.Bytes(), 0660); err != nil { return fmt.Errorf("Could not write node cache: %v", err) } return nil }
// ViewNode handles node views. func (h *nodeHandler) View(c *reqContext) error { // Redirect if trailing slash is missing and if this is not a file // node (in which case we write out the file's content). if c.Node.Path[len(c.Node.Path)-1] != '/' { if c.Node.Type.Id == "core.Image" || c.Node.Type.Id == "core.File" { c.Res.Header().Add("Last-Modified", c.Node.Changed.Format(time.RFC1123)) } if c.Node.Type.Id == "core.Image" { return h.viewImage(c) } else if c.Node.Type.Id == "core.File" { content, err := c.Serv.Monsti().GetNodeData(c.Site, c.Node.Path, "__file_core.File") if err != nil { return fmt.Errorf("Could not read file: %v", err) } c.Res.Write(content) } else { newPath, err := url.Parse(c.Node.Path + "/") if err != nil { serveError("Could not parse request URL: %v", err) } url := c.Req.URL.ResolveReference(newPath) http.Redirect(c.Res, c.Req, url.String(), http.StatusSeeOther) } return nil } var rendered []byte var err error mods := new(service.CacheMods) if c.UserSession.User == nil && len(c.Req.Form) == 0 { rendered, mods, err = c.Serv.Monsti().FromCache(c.Site, c.Node.Path, "core.page.partial") if err != nil { return fmt.Errorf("Could not get partial cache: %v", err) } } if rendered == nil { rendered, mods, err = h.RenderNode(c, nil) if err != nil { if e, ok := err.(errRedirect); ok { http.Redirect(c.Res, c.Req, e.URL, e.Status) return nil } return fmt.Errorf("Could not render node: %v", err) } if c.UserSession.User == nil && len(c.Req.Form) == 0 { if err := c.Serv.Monsti().ToCache(c.Site, c.Node.Path, "core.page.partial", rendered, mods); err != nil { return fmt.Errorf("Could not cache page: %v", err) } } } env := masterTmplEnv{Node: c.Node, Session: c.UserSession} content, renderMods := renderInMaster(h.Renderer, rendered, env, h.Settings, c.Site, c.SiteSettings, c.UserSession.Locale, c.Serv) mods.Join(renderMods) if c.UserSession.User == nil && len(c.Req.Form) == 0 { if err := c.Serv.Monsti().ToCache(c.Site, c.Node.Path, "core.page.full", content, mods); err != nil { return fmt.Errorf("Could not cache page: %v", err) } } c.Res.Write(content) return nil }