package main import ( "log" "net/http" "os" "github.com/bootdotdev/learn-file-storage-s3-golang-starter/internal/database" "github.com/google/uuid" "github.com/joho/godotenv" _ "github.com/lib/pq" ) type apiConfig struct { db database.Client jwtSecret string platform string filepathRoot string assetsRoot string s3Bucket string s3Region string s3CfDistribution string port string } type thumbnail struct { data []byte mediaType string } var videoThumbnails = map[uuid.UUID]thumbnail{} func main() { godotenv.Load(".env") pathToDB := os.Getenv("DB_PATH") if pathToDB == "" { log.Fatal("DB_URL must be set") } db, err := database.NewClient(pathToDB) if err != nil { log.Fatalf("Couldn't connect to database: %v", err) } jwtSecret := os.Getenv("JWT_SECRET") if jwtSecret == "" { log.Fatal("JWT_SECRET environment variable is not set") } platform := os.Getenv("PLATFORM") if platform == "" { log.Fatal("PLATFORM environment variable is not set") } filepathRoot := os.Getenv("FILEPATH_ROOT") if filepathRoot == "" { log.Fatal("FILEPATH_ROOT environment variable is not set") } assetsRoot := os.Getenv("ASSETS_ROOT") if assetsRoot == "" { log.Fatal("ASSETS_ROOT environment variable is not set") } s3Bucket := os.Getenv("S3_BUCKET") if s3Bucket == "" { log.Fatal("S3_BUCKET environment variable is not set") } s3Region := os.Getenv("S3_REGION") if s3Region == "" { log.Fatal("S3_REGION environment variable is not set") } s3CfDistribution := os.Getenv("S3_CF_DISTRO") if s3CfDistribution == "" { log.Fatal("S3_CF_DISTRO environment variable is not set") } port := os.Getenv("PORT") if port == "" { log.Fatal("PORT environment variable is not set") } cfg := apiConfig{ db: db, jwtSecret: jwtSecret, platform: platform, filepathRoot: filepathRoot, assetsRoot: assetsRoot, s3Bucket: s3Bucket, s3Region: s3Region, s3CfDistribution: s3CfDistribution, port: port, } err = cfg.ensureAssetsDir() if err != nil { log.Fatalf("Couldn't create assets directory: %v", err) } mux := http.NewServeMux() appHandler := http.StripPrefix("/app", http.FileServer(http.Dir(filepathRoot))) mux.Handle("/app/", appHandler) assetsHandler := http.StripPrefix("/assets", http.FileServer(http.Dir(assetsRoot))) mux.Handle("/assets/", cacheMiddleware(assetsHandler)) mux.HandleFunc("POST /api/login", cfg.handlerLogin) mux.HandleFunc("POST /api/refresh", cfg.handlerRefresh) mux.HandleFunc("POST /api/revoke", cfg.handlerRevoke) mux.HandleFunc("POST /api/users", cfg.handlerUsersCreate) mux.HandleFunc("POST /api/videos", cfg.handlerVideoMetaCreate) mux.HandleFunc("POST /api/thumbnail_upload/{videoID}", cfg.handlerUploadThumbnail) mux.HandleFunc("POST /api/video_upload/{videoID}", cfg.handlerUploadVideo) mux.HandleFunc("GET /api/videos", cfg.handlerVideosRetrieve) mux.HandleFunc("GET /api/videos/{videoID}", cfg.handlerVideoGet) mux.HandleFunc("GET /api/thumbnails/{videoID}", cfg.handlerThumbnailGet) mux.HandleFunc("DELETE /api/videos/{videoID}", cfg.handlerVideoMetaDelete) mux.HandleFunc("POST /admin/reset", cfg.handlerReset) srv := &http.Server{ Addr: ":" + port, Handler: mux, } log.Printf("Serving on: http://localhost:%s/app/\n", port) log.Fatal(srv.ListenAndServe()) }