github.com/blend/go-sdk@v1.20220411.3/web/cached_static_file.go (about) 1 /* 2 3 Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package web 9 10 import ( 11 "bytes" 12 "io" 13 "net/http" 14 "os" 15 "time" 16 17 "github.com/blend/go-sdk/ex" 18 "github.com/blend/go-sdk/logger" 19 "github.com/blend/go-sdk/webutil" 20 ) 21 22 // NewCachedStaticFile returns a new cached static file for a given path. 23 func NewCachedStaticFile(path string) (*CachedStaticFile, error) { 24 f, err := os.Open(path) 25 if err != nil { 26 return nil, ex.New(err) 27 } 28 defer f.Close() 29 30 finfo, err := f.Stat() 31 if err != nil { 32 return nil, ex.New(err) 33 } 34 35 contents, err := io.ReadAll(f) 36 if err != nil { 37 return nil, ex.New(err) 38 } 39 40 return &CachedStaticFile{ 41 Path: path, 42 Contents: bytes.NewReader(contents), 43 ModTime: finfo.ModTime(), 44 ETag: webutil.ETag(contents), 45 Size: len(contents), 46 }, nil 47 } 48 49 var ( 50 _ Result = (*CachedStaticFile)(nil) 51 ) 52 53 // CachedStaticFile is a memory mapped static file. 54 type CachedStaticFile struct { 55 Path string 56 Size int 57 ETag string 58 ModTime time.Time 59 Contents *bytes.Reader 60 } 61 62 // Render implements Result. 63 // 64 // Note: It is safe to ingore the error returned from this method; it only 65 // has this signature to satisfy the `Result` interface. 66 func (csf CachedStaticFile) Render(ctx *Ctx) error { 67 if csf.ETag != "" { 68 ctx.Response.Header().Set(webutil.HeaderETag, csf.ETag) 69 } 70 ctx.WithContext(logger.WithLabel(ctx.Context(), "web.static_file_cached", csf.Path)) 71 http.ServeContent(ctx.Response, ctx.Request, csf.Path, csf.ModTime, csf.Contents) 72 return nil 73 }