Example #1
0
func (m *Manager) scanFile(path string) (*file, error) {
	f := &file{
		fullpath: filepath.Join(m.cfg.Path, path),
	}

	fh, err := vfs.Open(f.fullpath)
	if err != nil {
		log.Debuge(err, "cannot find asset with path: ", f.fullpath)
		return f, nil
	}
	defer fh.Close()

	fi, err := fh.Stat()
	if err != nil {
		log.Debuge(err, "stat")
		return f, nil
	}

	f.mtime = fi.ModTime()

	h := sha256.New()
	_, err = io.Copy(h, fh)
	if err != nil {
		log.Debuge(err, "copy")
		return f, nil
	}

	hash := h.Sum(nil)
	f.sha256 = hash
	f.tag = base64.RawURLEncoding.EncodeToString(f.sha256)
	//f.tag = timeToTag(f.mtime)

	return f, nil
}
Example #2
0
// Serve static files from assets.
func (m *Manager) TryHandle(rw http.ResponseWriter, req *http.Request) error {
	if req.Method != "GET" && req.Method != "HEAD" {
		return ErrUnsupportedMethod
	}

	path, cachebuster := stripCachebuster(req.URL.Path) // "/img/x.png", "foobar"

	info := m.Info(path[1:])
	if info == nil {
		// May as well not bother with anything the asset manager can't find.  The
		// asset manager ensures that the final path is within the static root.
		return ErrNotFound
	}

	fpath := info.FullPath()
	f, err := vfs.Open(fpath)
	if err != nil {
		return err
	}

	defer f.Close()
	rw.Header().Set("Vary", "Accept-Encoding")
	if cachebuster != "" {
		// At some point we should probably check this to prevent cache poisoning
		// but it will break long-expiry for resources referenced from CSS files
		// since they will be in the same cachebuster 'directory' and thus have the
		// wrong tag. Alternatively, could move to unpredictable tags (ones not
		// based on modification tags.)
		//   && cachebuster == info.Tag() {

		rw.Header().Set("Expires", time.Now().Add(28*24*time.Hour).UTC().Format(time.RFC1123))
		rw.Header().Set("Cache-Control", "public, max-age=2419200")
	}

	// Currently, disable CSP for assets under the assumption that they are safe
	// and trusted. This is unfortunately necessary because some served SVG files
	// have inline SVG, and externalizing it would be quite overkill.
	rw.Header().Del("Content-Security-Policy")
	rw.Header().Del("Content-Security-Policy-Report-Only")

	http.ServeContent(rw, req, fpath, info.ModTime(), f)
	return nil
}
Example #3
0
// Load all templates from the given directory. The templates must have the file extension ".p2".
func LoadTemplates(dirname string) error {
	err := binarc.Setup(opts.BaseDir)
	if err != nil {
		return err
	}

	pongo2.OpenFunc = func(name string) (io.ReadCloser, error) {
		return vfs.Open(name)
	}

	c, err := loadTemplates(dirname)
	if err != nil {
		return err
	}

	for k, v := range c {
		templates[k] = v
	}

	return nil
}
Example #4
0
func loadTemplates(dirname string) (map[string]*pongo2.Template, error) {
	dir, err := vfs.Open(dirname)
	if err != nil {
		return nil, err
	}
	defer dir.Close()

	files, err := dir.Readdir(0)
	if err != nil {
		return nil, err
	}

	compiled := make(map[string]*pongo2.Template)
	for _, f := range files {
		fn := f.Name()
		fext := filepath.Ext(fn)
		path := filepath.Join(dirname, fn)

		if f.IsDir() {
			subcompiled, err := loadTemplates(path)
			if err != nil {
				return nil, err
			}

			for k, v := range subcompiled {
				compiled[filepath.Join(fn, k)] = v
			}
		} else if fext == ".p2" {
			tpl, err := pongo2.FromFile(path)
			if err != nil {
				return nil, err
			}

			k := fn[0 : len(fn)-len(fext)]
			compiled[k] = tpl
		}
	}

	return compiled, nil
}