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 }