// initScript concatenates all the javascript files needed to render // the tour UI and serves the result on /script.js. func initScript(root string) error { modTime := time.Now() b := new(bytes.Buffer) content, ok := static.Files["playground.js"] if !ok { return fmt.Errorf("playground.js not found in static files") } b.WriteString(content) // Keep this list in dependency order files := []string{ "static/lib/jquery.min.js", "static/lib/jquery-ui.min.js", "static/lib/angular.min.js", "static/lib/codemirror/lib/codemirror.js", "static/lib/codemirror/mode/go/go.js", "static/lib/angular-ui.min.js", "static/js/app.js", "static/js/controllers.js", "static/js/directives.js", "static/js/services.js", "static/js/values.js", } for _, file := range files { f, err := ioutil.ReadFile(filepath.Join(root, file)) if err != nil { return fmt.Errorf("couldn't open %v: %v", file, err) } _, err = b.Write(f) if err != nil { return fmt.Errorf("error concatenating %v: %v", file, err) } } var gzBuf bytes.Buffer gz, err := gzip.NewWriterLevel(&gzBuf, gzip.BestCompression) if err != nil { return err } gz.Write(b.Bytes()) gz.Close() http.HandleFunc("/script.js", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-type", "application/javascript") // Set expiration time in one week. w.Header().Set("Cache-control", "max-age=604800") if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { http.ServeContent(w, r, "", modTime, bytes.NewReader(b.Bytes())) } else { w.Header().Set("Content-Encoding", "gzip") http.ServeContent(w, r, "", modTime, bytes.NewReader(gzBuf.Bytes())) } }) return nil }
func (s *Server) serveResource(w http.ResponseWriter, r *http.Request, serveContent bool) { path := s.url2path(r.URL) f, err := s.Fs.Open(path) if err != nil { http.Error(w, r.RequestURI, StatusNotFound) return } defer f.Close() // TODO: what if path is collection? fi, err := f.Stat() if err != nil { http.Error(w, r.RequestURI, StatusNotFound) return } modTime := fi.ModTime() if serveContent { http.ServeContent(w, r, path, modTime, f) } else { // TODO: better way to send only head http.ServeContent(w, r, path, modTime, emptyFile{}) } }
// ServeArt provides a common method for serving and resizing Art, based on // an input HTTP request. func ServeArt(w http.ResponseWriter, r *http.Request, art *data.Art) error { // Attempt to access art data stream stream, err := art.Stream() if err != nil { return err } // Check for resize request, if none, serve directly size := r.URL.Query().Get("size") if size == "" { // Serve content directly, account for range headers, and enabling caching. http.ServeContent(w, r, art.FileName, time.Unix(art.LastModified, 0), stream) return nil } // Ensure size is a valid integer sizeInt, err := strconv.Atoi(size) if err != nil { return ErrInvalidIntegerSize } // Verify positive integer if sizeInt < 1 { return ErrNegativeIntegerSize } // Decode input image stream img, imgFormat, err := image.Decode(stream) if err != nil { return err } // Generate a thumbnail image of the specified size img = resize.Resize(uint(sizeInt), 0, img, resize.NearestNeighbor) // Encode to original format for output buffer := bytes.NewBuffer(nil) if imgFormat == "jpeg" { // JPEG, lossy encoding, default quality if err := jpeg.Encode(buffer, img, nil); err != nil { return err } } else { // Always send PNG as a backup // PNG, lossless encoding if err := png.Encode(buffer, img); err != nil { return err } } // Serve content directly, account for range headers, and enabling caching. http.ServeContent(w, r, art.FileName, time.Unix(art.LastModified, 0), bytes.NewReader(buffer.Bytes())) return nil }
func (m *Static) serveFile(w http.ResponseWriter, r *http.Request, name string) { if m.prefix != "" { name = strings.TrimPrefix(name, m.prefix) } if !m.noCache { if f, ok := m.c.GetOk(name); ok { http.ServeContent(w, r, f.Name(), f.ModTime(), f) return } } f, err := m.fs.Open(name) if err != nil { m.serveError(w, r, err) return } defer f.Close() nf, err := NewFromHTTPFile(f) if err != nil { m.serveError(w, r, err) return } supported := []string{".css", ".js"} var found bool xt := filepath.Ext(nf.Name()) for _, v := range supported { if v == xt { found = true break } } defer func() { if !m.noCache && found { m.c.Set(name, nf) } }() if nf.IsDir() { http.NotFound(w, r) return } if len(m.chains) > 0 { if found { for k := range m.chains { nf = m.chains[k](nf) } } } http.ServeContent(w, r, nf.Name(), nf.ModTime(), nf) }
func serveFile(w http.ResponseWriter, r *http.Request, fname string) { f, err := os.Open(fname) if err != nil { http.NotFound(w, r) return } defer f.Close() fi, err := f.Stat() if err == nil { http.ServeContent(w, r, fname, fi.ModTime(), f) } else { http.ServeContent(w, r, fname, time.Time{}, f) } }
func doConvert(l *log.Logger, w http.ResponseWriter, r *http.Request) error { in, _, e := r.FormFile("input") if e != nil { return e } data, e := ioutil.ReadAll(in) in.Close() if e != nil { return e } folder, e := NewZipFolder(data) if e != nil { return e } maker := NewEpubMaker(l) if e = maker.Process(folder, r.FormValue("duokan") == "duokan"); e != nil { return e } ver := EPUB_VERSION_300 if r.FormValue("epub2") == "epub2" { ver = EPUB_VERSION_200 } if data, name, e := maker.GetResult(ver); e != nil { return e } else { w.Header().Add("Content-Disposition", "attachment; filename="+name) http.ServeContent(w, r, name, time.Now(), bytes.NewReader(data)) } return nil }
func LogsPage(w http.ResponseWriter, r *http.Request) { name := r.URL.Path if i := strings.LastIndex(name, "/"); i >= 0 { name = name[i:] } name = filepath.Join(logDir, name) if r.Method == "POST" { if _, err := os.Stat(name); err != nil { fmt.Println("file doesn't exist:", name, "error:", err) http.Redirect(w, r, "/", http.StatusSeeOther) return } if name == errorName { if err := errorLog.Truncate(0); err != nil { errLog("truncate of error log failure: %v\n", err) } } else { if err := os.Remove(name); err != nil { errLog("delete file error: %v\n", err) } } http.Redirect(w, r, "/logs", http.StatusSeeOther) return } else if r.Method == "GET" { file, err := os.Open(name) if err != nil { http.NotFound(w, r) return } defer file.Close() fi, _ := file.Stat() w.Header().Set("Cache-control", "public, max-age=259200") http.ServeContent(w, r, name, fi.ModTime(), file) } }
// ServeHTTP uses w to serve current last MJPEG-frame // as JPG. It also reopens MJPEG-stream // if it was closed by idle timeout. func (m *Mjpegproxy) ServeHTTP(w http.ResponseWriter, req *http.Request) { select { case m.conChan <- time.Now(): default: m.lastConnLock.Lock() m.lastConn = time.Now() m.lastConnLock.Unlock() } buf := bytes.Buffer{} m.curImgLock.RLock() buf.Write(m.curImg.Bytes()) m.curImgLock.RUnlock() reader := bytes.NewReader(buf.Bytes()) if reader == nil { log.Println(m.mjpegStream, "ServeHTTP could not create bytes.Reader!") return } if !m.caching { w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") w.Header().Set("Pragma", "no-cache") w.Header().Set("Expires", "0") w.Header().Set("Last-Modified", time.Now().UTC().Format(http.TimeFormat)) reader.WriteTo(w) } else { m.lastModLock.RLock() modtime := m.lastModified m.lastModLock.RUnlock() if modtime.String() == "" { modtime = time.Now() } http.ServeContent(w, req, "img.jpg", modtime, reader) } }
func (h UserHandler) GetUser(w http.ResponseWriter, r *http.Request, userId uint64, userName string) { var u User err := h.Repo.View(repo.USER, func(tx *repo.Tx) error { var err error if userId == 0 { userId, err = tx.Lookup(userName) if err != nil { return err } } value, err := tx.Get(userId) if err != nil { return err } MustUnmarshalProto(value, &u) return nil }) if _, ok := err.(*repo.NotFoundError); ok { http.NotFound(w, r) return } if err != nil { log.Printf("error: GET /user %d %q: %v\n", userId, userName, err) http.Error(w, "Internal Server Error", 500) return } raw := MustMarshalJSON(&u) w.Header().Set(ContentType, MediaTypeJSON) w.Header().Set(CacheControl, CacheControlPublic) w.Header().Set(ETag, ETagFor(raw)) http.ServeContent(w, r, "", time.Time{}, bytes.NewReader(raw)) }
func doConvert(l *log.Logger, w http.ResponseWriter, r *http.Request) error { in, _, e := r.FormFile("input") if e != nil { return e } data, e := ioutil.ReadAll(in) in.Close() if e != nil { return e } folder, e := NewZipFolder(data) if e != nil { return e } maker := NewEpubMaker(l) if e = maker.Process(folder); e != nil { return e } data, name := maker.GetResult() w.Header().Add("Content-Disposition", "attachment; filename="+name) http.ServeContent(w, r, name, time.Now(), bytes.NewReader(data)) return nil }
func (file *FileStreamResult) Execute(ctx *HttpContext) error { //Set ContentType = "application/octet-stream"; if file.DownloadName != "" { ctx.SetHeader("Content-Disposition", "attachment; filename=\""+file.DownloadName+"\";") } if ctype := ctx.Resonse.Header().Get("Content-Type"); ctype == "" { ctype = file.Type() if ctype != "" { ctx.ContentType(ctype) } } if rs, ok := file.Data.(io.ReadSeeker); ok { http.ServeContent(ctx.Resonse, ctx.Request, file.DownloadName, file.ModifyTime, rs) return nil } if checkLastModified(ctx.Resonse, ctx.Request, file.ModifyTime) { return nil } io.Copy(ctx.Resonse, file.Data) return nil }
func ServeStatic(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) } else if data, ok := go_bindata[r.URL.Path]; !ok { http.NotFound(w, r) } else { if r.Header.Get("Range") != "" { // Bypass setting/checking ETag for range requests. } else if hash, ok := hashes[r.URL.Path]; ok { quotedHash := `"` + hash + `"` w.Header().Set("ETag", quotedHash) if r.Header.Get("If-None-Match") == quotedHash { w.WriteHeader(http.StatusNotModified) return } } ext := path.Ext(r.URL.Path) mimeType, ok := extToMime[ext] if !ok { mimeType = "application/octet-stream" } w.Header().Set("Content-Type", mimeType) http.ServeContent(w, r, "", time.Time{}, bytes.NewReader(data())) } }
//handleRoot return handler that handles url not defined other handlers. //if root, print titles of threads. if not, serve files on disk. func handleRoot() func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { gateway.PrintTitle(w, r) return } pathOnDisk := filepath.Join(cfg.Docroot, r.URL.Path) if util.IsFile(pathOnDisk) { http.ServeFile(w, r, pathOnDisk) return } pathOnAsset := path.Join("www", r.URL.Path) if c, err := util.Asset(pathOnAsset); err == nil { i, err := util.AssetInfo(pathOnAsset) if err != nil { log.Fatal(err) } reader := bytes.NewReader(c) http.ServeContent(w, r, path.Base(r.URL.Path), i.ModTime(), reader) return } log.Println("not found", r.URL.Path) http.NotFound(w, r) } }
func TestFetchWithContentLength(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { file, err := os.Open("./fixtures/test") assert.Ok(t, err) assert.Cond(t, file != nil, "Failed loading fixture file") defer file.Close() http.ServeContent(w, r, file.Name(), time.Time{}, file) })) defer ts.Close() progressCh := make(chan ProgressReport) done := make(chan bool) destDir, err := ioutil.TempDir(os.TempDir(), "content-length") assert.Ok(t, err) defer os.RemoveAll(destDir) gf := New(WithDestDir(destDir), WithConcurrency(50)) go func() { _, err := gf.Fetch(ts.URL, progressCh) assert.Ok(t, err) done <- true }() var total int64 for p := range progressCh { //fmt.Printf("\r%d of %d", p.WrittenBytes, p.Total) total += p.WrittenBytes } assert.Equals(t, int64(10485760), total) <-done }
func serveJpeg() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.ServeContent(w, r, file_name, time.Now(), bytes.NewReader(getJpeg())) }) log.Fatal(http.ListenAndServe(test_server, nil)) }
func (e *Echo) serveFile(dir, file string, c *Context) (err error) { fs := http.Dir(dir) f, err := fs.Open(file) if err != nil { return NewHTTPError(http.StatusNotFound) } defer f.Close() fi, _ := f.Stat() if fi.IsDir() { /* NOTE: Not checking the Last-Modified header as it caches the response `304` when changing differnt directories for the same path. */ d := f // Index file file = path.Join(file, indexPage) f, err = fs.Open(file) if err != nil { if e.autoIndex { // Auto index return listDir(d, c) } return NewHTTPError(http.StatusForbidden) } fi, _ = f.Stat() // Index file stat } http.ServeContent(c.response, c.request, fi.Name(), fi.ModTime(), f) return }
func listReleases(w http.ResponseWriter, r *http.Request) { rels := make([]release, 0) rows, err := db.Query(`select plat, cmd, ver, sha256 from release`) if err != nil { log.Println(err) http.Error(w, "internal error", 500) return } for rows.Next() { var rel release err := rows.Scan(&rel.Plat, &rel.Cmd, &rel.Ver, &rel.Sha256) if err != nil { log.Println(err) } else { rels = append(rels, rel) } } if err := rows.Err(); err != nil { log.Println(err) http.Error(w, "internal error", 500) return } b := new(bytes.Buffer) if err = json.NewEncoder(b).Encode(rels); err != nil { log.Println(err) http.Error(w, "internal error", 500) return } var mod time.Time db.QueryRow(`select t from mod`).Scan(&mod) http.ServeContent(w, r, "", mod, bytes.NewReader(b.Bytes())) }
func handleImageRequest(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { w.WriteHeader(http.StatusMethodNotAllowed) } w.Header().Set("Cache-Control", "public, max-age=31536000") // Client is checking for a cached URI, assume it is valid // and return a 304 if r.Header.Get("If-Modified-Since") != "" { w.WriteHeader(http.StatusNotModified) return } gc := fetch.RequestContext(r) var data []byte err := cache.Get(gc, gc.CacheKey(), groupcache.AllocatingByteSliceSink(&data)) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } w.Header().Set("Content-Type", http.DetectContentType(data)) http.ServeContent(w, r, gc.ImageId, time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), bytes.NewReader(data)) }
func serveDashboardJs(res http.ResponseWriter, req *http.Request, conf *Config) { file := filepath.Join(conf.StaticPath, "assets", filepath.Base(req.URL.Path)) f, err := os.Open(file) if err != nil { fmt.Println(err) res.WriteHeader(500) return } defer f.Close() fi, err := f.Stat() if err != nil { fmt.Println(err) return } jsConf := strings.NewReader(fmt.Sprintf(` window.DashboardConfig = { API_SERVER: "%s", PATH_PREFIX: "%s", INSTALL_CERT: true }; `, conf.URL, conf.PathPrefix)) r := ioutil.NewMultiReadSeeker(jsConf, f) http.ServeContent(res, req, file, fi.ModTime(), r) }
func (r *StaticBinaryResult) Apply(req *revel.Request, resp *revel.Response) { // If we have a ReadSeeker, delegate to http.ServeContent if rs, ok := r.Reader.(io.ReadSeeker); ok { // http.ServeContent doesn't know about response.ContentType, so we set the respective header. if resp.ContentType != "" { resp.Out.Header().Set("Content-Type", resp.ContentType) } else { contentType := revel.ContentTypeByFilename(r.Name) resp.Out.Header().Set("Content-Type", contentType) } http.ServeContent(resp.Out, req.Request, r.Name, r.ModTime, rs) } else { // Else, do a simple io.Copy. if r.Length != -1 { resp.Out.Header().Set("Content-Length", strconv.FormatInt(r.Length, 10)) } resp.WriteHeader(http.StatusOK, revel.ContentTypeByFilename(r.Name)) io.Copy(resp.Out, r.Reader) } // Close the Reader if we can if v, ok := r.Reader.(io.Closer); ok { v.Close() } }
// StaticMiddlewareFromDir returns a middleware that serves static files from the specified http.FileSystem. // This middleware is great for development because each file is read from disk each time and no // special caching or cache headers are sent. // // If a path is requested which maps to a folder with an index.html folder on your filesystem, // then that index.html file will be served. func StaticMiddlewareFromDir(dir http.FileSystem, options ...StaticOption) func(ResponseWriter, *Request, NextMiddlewareFunc) { var option StaticOption if len(options) > 0 { option = options[0] } return func(w ResponseWriter, req *Request, next NextMiddlewareFunc) { if req.Method != "GET" && req.Method != "HEAD" { next(w, req) return } file := req.URL.Path if option.Prefix != "" { if !strings.HasPrefix(file, option.Prefix) { next(w, req) return } file = file[len(option.Prefix):] } f, err := dir.Open(file) if err != nil { next(w, req) return } defer f.Close() fi, err := f.Stat() if err != nil { next(w, req) return } // If the file is a directory, try to serve an index file. // If no index is available, DO NOT serve the directory to avoid // Content-Length issues. Simply skip to the next middleware, and return // a 404 if no path with the same name is handled. if fi.IsDir() { if option.IndexFile != "" { file = filepath.Join(file, option.IndexFile) f, err = dir.Open(file) if err != nil { next(w, req) return } defer f.Close() fi, err = f.Stat() if err != nil || fi.IsDir() { next(w, req) return } } else { next(w, req) return } } http.ServeContent(w, req.Request, file, fi.ModTime(), f) } }
func (a asset) ServeHTTP(w http.ResponseWriter, req *http.Request) { if a.etag != "" && w.Header().Get("ETag") == "" { w.Header().Set("ETag", a.etag) } body := strings.NewReader(a.Content) http.ServeContent(w, req, a.Name, time.Time{}, body) }
func handleGet(p ent.Provider, fs ent.FileSystem) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var ( bucket = r.URL.Query().Get(ent.KeyBucket) key = r.URL.Query().Get(ent.KeyBlob) ) b, err := p.Get(bucket) if err != nil { respondError(w, r, err) return } f, err := fs.Open(b, key) if err != nil { respondError(w, r, err) return } defer f.Close() err = writeBlobHeaders(w, f) if err != nil { respondError(w, r, err) return } http.ServeContent(w, r, key, f.LastModified(), f) } }
func PhotoDownloadGET(w http.ResponseWriter, r *http.Request) { // Get session sess := session.Instance(r) var params = context.Get(r, "params").(httprouter.Params) //userid := params.ByName("userid") pic_id := params.ByName("picid") //user_id, _ := strconv.Atoi(userid) user_id := uint64(sess.Values["id"].(uint32)) userid := strconv.Itoa(int(user_id)) if allowed, mark, err := photoAccessAllowed(r, user_id, pic_id); allowed { buffer, err := renderImage(w, r, userid, pic_id, mark) if err != nil { log.Println(err) Error500(w, r) return } // Force download w.Header().Set("Content-Disposition", `attachment; filename="`+pic_id+`"`) w.Header().Set("Content-Type", r.Header.Get("Content-Type")) http.ServeContent(w, r, pic_id, time.Now(), bytes.NewReader(buffer.Bytes())) } else if err != sql.ErrNoRows { log.Println(err) Error500(w, r) return } else { //log.Println("User does not have access to the photo.") Error401(w, r) return } }
func (h *Handler) handleGetHeadPost(w http.ResponseWriter, r *http.Request) (status int, err error) { reqPath, status, err := h.stripPrefix(r.URL.Path) if err != nil { return status, err } // TODO: check locks for read-only access?? f, err := h.FileSystem.OpenFile(reqPath, os.O_RDONLY, 0) if err != nil { return http.StatusNotFound, err } defer f.Close() fi, err := f.Stat() if err != nil { return http.StatusNotFound, err } if fi.IsDir() { return http.StatusMethodNotAllowed, nil } etag, err := findETag(h.FileSystem, h.LockSystem, reqPath, fi) if err != nil { return http.StatusInternalServerError, err } w.Header().Set("ETag", etag) // Let ServeContent determine the Content-Type header. http.ServeContent(w, r, reqPath, fi.ModTime(), f) return 0, nil }
func Thumb(args martini.Params, res http.ResponseWriter, req *http.Request) { file := args["name"] org_dir := utils.ImageCfg.Root() temp_dir := utils.ImageCfg.Thumbs() org_file := org_dir + file temp_file := temp_dir + file if !Exists(temp_file) { okc := make(chan bool, 1) go utils.CreateThumb(okc, org_file, temp_file, 150, 150) <-okc } dir := http.Dir(temp_dir) f, err := dir.Open(file) if err != nil { log.Println(err) return } defer f.Close() fi, err := f.Stat() if err != nil { return } res.Header().Set("X-Content-Type-Options", "nosniff") res.Header().Set("Expires", utils.ExpiresHeader()) http.ServeContent(res, req, file, fi.ModTime(), f) }
func (sh *StaticHandler) ServeHttp(responseWriter http.ResponseWriter, request *http.Request) { staticFilePath := staticFilePath(request) fileHandle, error := sh.Open(staticFilePath) if serve404OnErr(error, responseWriter) { return } defer fileHandle.Close() fileInfo, error := fileHandle.Stat() if serve404OnErr(error, responseWriter) { return } if fileInfo.IsDir() { if request.URL.Path[len(request.URL.Path)-1] != '/' { http.Redirect(responseWriter, request, request.URL.Path+"/", http.StatusFound) return } fileHandle, error = sh.Open(staticFilePath + "/index.html") if serve404OnErr(error, responseWriter) { return } defer fileHandle.Close() fileInfo, error = fileHandle.Stat() if serve404OnErr(error, responseWriter) { return } } http.ServeContent(responseWriter, request, fileInfo.Name(), fileInfo.ModTime(), fileHandle) }
func (r *fileResponse) Render(w http.ResponseWriter) error { w.Header().Set("Content-Type", "application/octet-stream") f, err := os.Open(r.path) if err != nil { return err } defer f.Close() fi, err := f.Stat() if err != nil { return err } if r.headers != nil { for k, v := range r.headers { w.Header().Set(k, v) } } http.ServeContent(w, r.req, r.filename, fi.ModTime(), f) if r.removeAfterServe { os.Remove(r.filename) } return nil }
// serveFile() serve any request with content pointed by abspath. func serveFile(w http.ResponseWriter, r *http.Request, abspath string) error { f, err := os.Open(abspath) if err != nil { return err } info, err := f.Stat() if err != nil { return err } if info.IsDir() { return errors.New("Cannot serve content of a directory") } filename := info.Name() // TODO if client (use JavaScript) send a request head: 'Accept: "application/octet-stream"' then write the download header ? // if the url contains a query like "?download", then download this file _, ok := r.URL.Query()["download"] if ok { hhelper.WriteDownloadHeader(w, filename) } // http.ServeContent() always return a status code of 200. http.ServeContent(w, r, filename, info.ModTime(), f) return nil }
func serveFile(w http.ResponseWriter, r *http.Request, fs http.FileSystem, name string, redirect bool, disableCache bool) { // try to serve gziped file; ignore request for gz files if !strings.HasSuffix(strings.ToLower(name), ".gz") && supportsGzip(r) { if file, stat, err := open(fs, name+".gz"); file != nil && err == nil { defer file.Close() setContentType(w, name, file) w.Header().Set("Content-Encoding", "gzip") if disableCache { w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0") w.Header().Set("Pragma", "no-cache") } else { w.Header().Set("Cache-Control", "must_revalidate, private, max-age=604800") } http.ServeContent(w, r, name, stat.ModTime(), file) return } } // serve requested file if file, stat, err := open(fs, name); file != nil && err == nil { defer file.Close() if disableCache { w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0") w.Header().Set("Pragma", "no-cache") } else { w.Header().Set("Cache-Control", "must_revalidate, private, max-age=604800") } http.ServeContent(w, r, stat.Name(), stat.ModTime(), file) } else { log.Error("Asset open error", "name", name, "err", err.Error()) http.NotFound(w, r) } }