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  }