package main import ( "bytes" "fmt" "net/http" "os" "time" "git.makerforce.io/photos/photos/internal/httphelpers" lib "git.makerforce.io/photos/photos/pkg/bucket" "git.makerforce.io/photos/photos/pkg/credentials" "git.makerforce.io/photos/photos/pkg/signer" "git.makerforce.io/photos/photos/web" ) var creds *credentials.Client var sig *signer.Signer var sharedFileServer http.Handler var endpoint string var controlEndpoint string func main() { var err error // Setup bucket credential source creds, err = credentials.NewClientFromEnv() if err != nil { panic(err) } // Setup bucket signer sig, err = signer.NewSignerFromEnv() if err != nil { panic(err) } transport := &http.Transport{ MaxIdleConns: 4, MaxIdleConnsPerHost: 4, IdleConnTimeout: 60 * time.Second, DisableCompression: true, } http.DefaultClient = &http.Client{ Transport: transport, Timeout: 60 * time.Second, } // Read configuration endpoint = os.Getenv("WEB_ENDPOINT") controlEndpoint = os.Getenv("CONTROL_ENDPOINT") sharedFileServer = http.FileServer(http.FS(web.FS)) server := &http.Server{ Addr: ":8004", ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } http.HandleFunc("/shared/", shared) http.HandleFunc("/update", update) err = server.ListenAndServe() if err != nil { panic(err) } } func shared(w http.ResponseWriter, req *http.Request) { // For static files, allow all CORS w.Header().Add("Access-Control-Allow-Origin", "*") sharedFileServer.ServeHTTP(w, req) } func update(w http.ResponseWriter, req *http.Request) { var err error if req.Method != http.MethodPost { err := fmt.Errorf("%w: %v", httphelpers.ErrorMethodNotAllowed, req.Method) httphelpers.ErrorResponse(w, err) return } bucket := lib.Bucket(req.FormValue("bucket")) err = bucket.Validate() if err != nil { err := fmt.Errorf("%w: %v", httphelpers.ErrorBadRequest, err.Error()) httphelpers.ErrorResponse(w, err) return } var cred credentials.Credential cred, err = creds.Get(bucket) if err != nil { err := fmt.Errorf("%w: error getting credentials: %v", httphelpers.ErrorBadRequest, err.Error()) httphelpers.ErrorResponse(w, err) return } title, err := getBucketMetadataTitle(bucket, cred) if err != nil { /* err := fmt.Errorf("bucket title: %w", err) httphelpers.ErrorResponse(w, err) return */ title = "" } photos, err := getPhotos(bucket, cred) if err != nil { err := fmt.Errorf("cannot list bucket: %w", err) httphelpers.ErrorResponse(w, err) return } detailedPhotos := make([]Photo, 0) for _, photo := range photos { size, err := getPhotoMetadataSize(bucket, cred, photo) if err != nil { err := fmt.Errorf("photo size: %w: %v", err, photo) httphelpers.ErrorResponse(w, err) return } title, err := getPhotoMetadataTitle(bucket, cred, photo) if err != nil { err := fmt.Errorf("photo title: %w: %v", err, photo) httphelpers.ErrorResponse(w, err) return } tags, err := getPhotoMetadataTags(bucket, cred, photo) if err != nil { err := fmt.Errorf("photo tags: %w: %v", err, photo) httphelpers.ErrorResponse(w, err) return } detailedPhotos = append(detailedPhotos, Photo{photo, size, title, tags}) } data := IndexTemplateData{ Assets: endpoint + "/shared/", Control: controlEndpoint, Bucket: bucket, Title: title, Photos: detailedPhotos, } buf := new(bytes.Buffer) err = viewTemplate.Execute(buf, data) if err != nil { httphelpers.ErrorResponse(w, err) return } err = putBucketView(bucket, cred, buf.Bytes()) if err != nil { httphelpers.ErrorResponse(w, err) return } buf.Reset() err = manageTemplate.Execute(buf, data) if err != nil { httphelpers.ErrorResponse(w, err) return } err = putBucketManage(bucket, cred, buf.Bytes()) if err != nil { httphelpers.ErrorResponse(w, err) return } }