github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/snapshots/server.go (about)

     1  package snapshots
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/json"
     7  	"fmt"
     8  	"net"
     9  	"net/http"
    10  
    11  	"github.com/tilt-dev/tilt/pkg/assets"
    12  )
    13  
    14  func Serve(ctx context.Context, l net.Listener, rawSnapshot []byte) error {
    15  	buf := bytes.NewReader(rawSnapshot)
    16  	var snapshot map[string]interface{}
    17  
    18  	err := json.NewDecoder(buf).Decode(&snapshot)
    19  	if err != nil {
    20  		return err
    21  	}
    22  
    23  	ss, err := newSnapshotServer(rawSnapshot)
    24  	if err != nil {
    25  		return err
    26  	}
    27  
    28  	go func() {
    29  		<-ctx.Done()
    30  		_ = ss.server.Shutdown(context.Background())
    31  	}()
    32  
    33  	err = ss.serve(l)
    34  	if err != nil && err != http.ErrServerClosed {
    35  		return err
    36  	}
    37  	return nil
    38  }
    39  
    40  type snapshotServer struct {
    41  	assetServer assets.Server
    42  	snapshot    []byte
    43  	server      http.Server
    44  }
    45  
    46  func newSnapshotServer(snapshot []byte) (*snapshotServer, error) {
    47  	result := &snapshotServer{}
    48  
    49  	s, ok := assets.GetEmbeddedServer()
    50  	if !ok {
    51  		return nil, fmt.Errorf(
    52  			("requested embedded mode, but JS/CSS files are not available.\n" +
    53  				"Please report this: https://github.com/tilt-dev/tilt/issues"))
    54  	}
    55  	result.assetServer = s
    56  	result.snapshot = snapshot
    57  
    58  	return result, nil
    59  }
    60  
    61  func (ss *snapshotServer) serve(l net.Listener) error {
    62  	m := http.NewServeMux()
    63  
    64  	m.HandleFunc("/api/snapshot/local", ss.snapshotJSONHandler(ss.snapshot))
    65  	m.HandleFunc("/", ss.assetServer.ServeHTTP)
    66  
    67  	ss.server = http.Server{Handler: m}
    68  	return ss.server.Serve(l)
    69  }
    70  
    71  func (ss *snapshotServer) snapshotJSONHandler(snapshot []byte) http.HandlerFunc {
    72  	return func(w http.ResponseWriter, req *http.Request) {
    73  		_, err := w.Write(snapshot)
    74  		if err != nil {
    75  			http.Error(w, fmt.Sprintf("error writing snapshot to http response: %v", err.Error()), http.StatusInternalServerError)
    76  		}
    77  	}
    78  }