package main import ( "context" "fmt" "io" "log" "net/http" "os" "strconv" "github.com/gin-gonic/gin" "github.com/jackc/pgx/v5/pgxpool" "github.com/jaswdr/faker" ) // This is taken from our DB model type video struct { ID int `json:"id"` Filepath string `json:"filepath"` } // videos slice to seed record video data. var videos []video func main() { dbpool, err := pgxpool.New(context.Background(), "postgresql://postgres:postgres@172.19.0.2:5432/postgres") if err != nil { log.Fatal(err) } defer dbpool.Close() sqlStmt := ` DROP TABLE IF EXISTS public.videos; CREATE TABLE IF NOT EXISTS public.videos ( id integer NOT NULL, filepath text, CONSTRAINT videos_pkey PRIMARY KEY (id) ) TABLESPACE pg_default; ALTER TABLE IF EXISTS public.videos OWNER to postgres; ` _, err = dbpool.Exec(context.Background(), sqlStmt) if err != nil { log.Fatalf("Unable to connection to database: %v\n", err) } faker := faker.New() for i := 0; i < 10; i++ { sqlStmt = fmt.Sprintf("insert into public.videos(id, filepath) values(%d, '%s')", i, faker.File().AbsoluteFilePathForUnix(2)) _, err = dbpool.Exec(context.Background(), sqlStmt) if err != nil { log.Fatalf("Unable to add videos: %v\n", err) } } rows, _ := dbpool.Query(context.Background(), "select * from videos") for rows.Next() { var id int var name string err = rows.Scan(&id, &name) if err != nil { log.Fatalf("Unable to list videos: %v\n", err) } fmt.Println(id, name) } err = rows.Err() if err != nil { log.Fatalf("Unable to list videos: %v\n", err) } // Legacy for i := 0; i < 10; i++ { videos = append(videos, video{ID: i, Filepath: faker.File().AbsoluteFilePathForUnix(5)}) } router := gin.Default() router.SetTrustedProxies(nil) router.POST("/upload", ReceiveFile) router.GET("/videos", getvideos) router.GET("/videos/:id", getvideoByID) router.POST("/videos", postvideos) router.DELETE("/videos", delvideos) router.DELETE("/videos/:id", delvideoByID) router.PATCH("/videos/:id", updatevideo) router.Run("localhost:8080") } func remove(slice []video, s int) []video { return append(slice[:s], slice[s+1:]...) } func ReceiveFile(c *gin.Context) { // maybe even re-verify mime-type (before or after upload) fileName := c.GetHeader("file-name") /* get data from request write append data to file */ data, err := io.ReadAll(c.Request.Body) if err != nil { c.IndentedJSON(http.StatusBadRequest, "Unknown Error") return } f, err := os.OpenFile(fileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Fatal(err) } if _, err := f.Write(data); err != nil { log.Fatal(err) } if err := f.Close(); err != nil { log.Fatal(err) } c.IndentedJSON(http.StatusOK, "Received chunk") } // getvideos responds with the list of all videos as JSON. func getvideos(c *gin.Context) { c.IndentedJSON(http.StatusOK, videos) } // postvideos adds an video from JSON received in the request body. func postvideos(c *gin.Context) { var newvideo video // Call BindJSON to bind the received JSON to // newvideo. if err := c.BindJSON(&newvideo); err != nil { c.Status(http.StatusBadRequest) return } for _, a := range videos { if a == newvideo { c.Status(http.StatusBadRequest) return } } // Add the new video to the slice. videos = append(videos, newvideo) c.IndentedJSON(http.StatusCreated, newvideo) } // getvideoByID locates the video whose ID value matches the id // parameter sent by the client, then returns that video as a response. func getvideoByID(c *gin.Context) { inputId := c.Param("id") // Loop through the list of videos, looking for // an video whose ID value matches the parameter. for _, a := range videos { if strconv.Itoa(a.ID) == inputId { c.IndentedJSON(http.StatusOK, a) return } } c.IndentedJSON(http.StatusNotFound, gin.H{"message": "video not found"}) } func delvideos(c *gin.Context) { videos = []video{} c.IndentedJSON(http.StatusOK, videos) } func delvideoByID(c *gin.Context) { inputId := c.Param("id") for s, a := range videos { if strconv.Itoa(a.ID) == inputId { videos = remove(videos, s) c.IndentedJSON(http.StatusCreated, videos) return } } c.IndentedJSON(http.StatusNotFound, gin.H{"message": "video not found"}) } func updatevideo(c *gin.Context) { inputId := c.Param("id") var newvideo video if err := c.BindJSON(&newvideo); err != nil { return } for s, a := range videos { if strconv.Itoa(a.ID) == inputId { videos = remove(videos, s) videos = append(videos, newvideo) c.IndentedJSON(http.StatusCreated, newvideo) return } } c.IndentedJSON(http.StatusNotFound, gin.H{"message": "video not found"}) }