Compare commits

..

3 Commits

Author SHA1 Message Date
7c782522f5
finish initUpload 2024-06-03 19:36:41 +02:00
bc278868da
CRUD mostly implemented 2024-06-01 13:58:16 +02:00
3df71a8302
can now create and read 2024-05-19 00:19:47 +02:00

272
main.go
View File

@ -14,196 +14,218 @@ import (
"github.com/jaswdr/faker" "github.com/jaswdr/faker"
) )
// This is taken from our DB model var dbpool *pgxpool.Pool
type video struct {
ID int `json:"id"`
Filepath string `json:"filepath"`
}
// videos slice to seed record video data.
var videos []video
func main() { func main() {
dbpool, err := pgxpool.New(context.Background(), "postgresql://postgres:postgres@172.19.0.2:5432/postgres") var err error
dbpool, err = pgxpool.New(context.Background(), "postgresql://postgres:postgres@172.19.0.2:5432/postgres")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer dbpool.Close() defer dbpool.Close()
sqlStmt := ` sqlStmt := `
DROP TABLE IF EXISTS public.videos; DROP TABLE IF EXISTS videos;
CREATE TABLE IF NOT EXISTS public.videos CREATE TABLE IF NOT EXISTS videos
( (
id integer NOT NULL, id serial NOT NULL,
filepath text, filepath text,
CONSTRAINT videos_pkey PRIMARY KEY (id) CONSTRAINT videos_pkey PRIMARY KEY (id)
) )
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.videos
OWNER to postgres;
` `
_, err = dbpool.Exec(context.Background(), sqlStmt) _, err = dbpool.Exec(context.Background(), sqlStmt)
if err != nil { if err != nil {
log.Fatalf("Unable to connection to database: %v\n", err) log.Fatalf("main: create table: %v\n", err)
} }
faker := faker.New() faker := faker.New()
for i := 0; i < 10; i++ { 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(), "insert into videos(filepath) values($1)", faker.File().AbsoluteFilePathForUnix(2))
_, err = dbpool.Exec(context.Background(), sqlStmt)
if err != nil { if err != nil {
log.Fatalf("Unable to add videos: %v\n", err) log.Fatalf("main: fill with fake data: %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 := gin.Default()
router.SetTrustedProxies(nil) router.SetTrustedProxies(nil)
router.POST("/upload", ReceiveFile) router.POST("/video/init", initUpload)
router.GET("/videos", getvideos) router.POST("/video/chunk", ReceiveChunk)
router.GET("/videos/:id", getvideoByID) router.POST("/video/completed", finishUpload)
router.POST("/videos", postvideos) router.GET("/videos", listVideos)
router.DELETE("/videos", delvideos) router.GET("/videos/:id", getVideo)
router.DELETE("/videos/:id", delvideoByID) router.DELETE("/videos/:id", deleteVideo)
router.PATCH("/videos/:id", updatevideo)
router.Run("localhost:8080") router.Run("localhost:8080")
} }
func remove(slice []video, s int) []video { func initUpload(c *gin.Context) {
return append(slice[:s], slice[s+1:]...) var err error
}
func ReceiveFile(c *gin.Context) { fileName, err := io.ReadAll(c.Request.Body)
// 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 { if err != nil {
c.IndentedJSON(http.StatusBadRequest, "Unknown Error") c.JSON(http.StatusBadRequest, "Couldn't read html request body")
return return
} }
f, err := os.OpenFile(fileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) currentDir, err := os.Getwd()
if err != nil { if err != nil {
c.JSON(http.StatusInternalServerError, "")
log.Fatalf("initUpload: %v\n", err)
}
rows, _ := dbpool.Query(context.Background(), "select filepath from videos")
for rows.Next() {
var filepath string
err = rows.Scan(&filepath)
if err != nil {
c.JSON(http.StatusInternalServerError, "")
log.Fatalf("initUpload: %v\n", err)
}
fmt.Println(filepath)
if filepath == fmt.Sprintf("%s/%s", currentDir, fileName) {
c.JSON(http.StatusForbidden, "File already exists")
return
}
}
err = rows.Err()
if err != nil {
c.JSON(http.StatusInternalServerError, "")
log.Fatalf("initUpload: %v\n", err)
}
c.JSON(http.StatusOK, "Upload can proceed")
}
func ReceiveChunk(c *gin.Context) {
chunk, err := io.ReadAll(c.Request.Body)
if err != nil {
c.JSON(http.StatusBadRequest, "Couldn't read html request body")
return
}
f, err := os.OpenFile(c.GetHeader("file-name"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
c.JSON(http.StatusInternalServerError, "")
log.Fatal(err) log.Fatal(err)
} }
if _, err := f.Write(data); err != nil { if _, err := f.Write(chunk); err != nil {
c.JSON(http.StatusInternalServerError, "")
log.Fatal(err) log.Fatal(err)
} }
if err := f.Close(); err != nil { if err := f.Close(); err != nil {
c.JSON(http.StatusInternalServerError, "")
log.Fatal(err) log.Fatal(err)
} }
c.IndentedJSON(http.StatusOK, "Received chunk") c.JSON(http.StatusOK, "Received chunk")
} }
// getvideos responds with the list of all videos as JSON. func finishUpload(c *gin.Context) {
func getvideos(c *gin.Context) { currentDir, err := os.Getwd()
c.IndentedJSON(http.StatusOK, videos) if err != nil {
} c.JSON(http.StatusInternalServerError, "")
log.Fatalf("finishUpload: %v\n", err)
}
// postvideos adds an video from JSON received in the request body. fileName, err := io.ReadAll(c.Request.Body)
func postvideos(c *gin.Context) { if err != nil {
var newvideo video c.JSON(http.StatusBadRequest, "Couldn't read html request body")
// Call BindJSON to bind the received JSON to
// newvideo.
if err := c.BindJSON(&newvideo); err != nil {
c.Status(http.StatusBadRequest)
return return
} }
for _, a := range videos { _, err = dbpool.Exec(context.Background(), "insert into videos(filepath) values($1)", fmt.Sprintf("%s/%s", currentDir, fileName))
if a == newvideo { if err != nil {
c.Status(http.StatusBadRequest) c.JSON(http.StatusInternalServerError, "")
return log.Fatalf("finishUpload: %v\n", err)
}
} }
// Add the new video to the slice. c.JSON(http.StatusOK, gin.H{}) // return list of videos
videos = append(videos, newvideo)
c.IndentedJSON(http.StatusCreated, newvideo)
} }
// getvideoByID locates the video whose ID value matches the id func listVideos(c *gin.Context) {
// parameter sent by the client, then returns that video as a response. var err error
func getvideoByID(c *gin.Context) { rows, _ := dbpool.Query(context.Background(), "select * from videos")
inputId := c.Param("id") for rows.Next() {
var id int
// Loop through the list of videos, looking for var filepath string
// an video whose ID value matches the parameter. err = rows.Scan(&id, &filepath)
for _, a := range videos { if err != nil {
if strconv.Itoa(a.ID) == inputId { c.JSON(http.StatusInternalServerError, "")
c.IndentedJSON(http.StatusOK, a) log.Fatalf("listVideos: %v\n", err)
return
} }
fmt.Println(id, filepath)
} }
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "video not found"}) err = rows.Err()
} if err != nil {
c.JSON(http.StatusInternalServerError, "")
func delvideos(c *gin.Context) { log.Fatalf("listVideos: %v\n", err)
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"})
c.JSON(http.StatusOK, gin.H{})
} }
func updatevideo(c *gin.Context) { func getVideo(c *gin.Context) {
inputId := c.Param("id") var err error
inputId, err := strconv.Atoi(c.Param("id"))
if err != nil {
log.Fatal(err)
}
var newvideo video rows, _ := dbpool.Query(context.Background(), "select * from videos where id = $1", inputId)
rows.Next()
var id int
var filepath string
err = rows.Scan(&id, &filepath)
if err != nil {
c.JSON(http.StatusInternalServerError, "")
log.Fatalf("getVideo: %v\n", err)
}
fmt.Println(id, filepath)
err = rows.Err()
if err != nil {
c.JSON(http.StatusInternalServerError, "")
log.Fatalf("getVideo: %v\n", err)
}
if err := c.BindJSON(&newvideo); err != nil { c.JSON(http.StatusOK, gin.H{})
}
func deleteVideo(c *gin.Context) {
inputId, err := strconv.Atoi(c.Param("id"))
if err != nil {
log.Fatal(err)
}
rows, _ := dbpool.Query(context.Background(), "select filepath from videos where id = $1", inputId)
rows.Next()
var filepath string
err = rows.Scan(&filepath)
if err != nil {
log.Printf("deleteVideo: %v\n", err)
c.JSON(http.StatusBadRequest, "Video does not exist")
return
}
fmt.Println(filepath)
err = rows.Err()
if err != nil {
log.Printf("deleteVideo: %v\n", err)
c.JSON(http.StatusInternalServerError, "Scanning the row didn't work")
return return
} }
for s, a := range videos { _, err = dbpool.Exec(context.Background(), "delete from videos where id = $1", inputId)
if strconv.Itoa(a.ID) == inputId { if err != nil {
videos = remove(videos, s) c.JSON(http.StatusInternalServerError, "")
videos = append(videos, newvideo) log.Fatalf("deleteVideo: %v\n", err)
c.IndentedJSON(http.StatusCreated, newvideo)
return
}
} }
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "video not found"})
if err = os.Remove(filepath); err != nil {
c.JSON(http.StatusInternalServerError, "")
log.Fatalf("deleteVideo: %v\n", err)
}
c.JSON(http.StatusOK, gin.H{}) // return list of videos
} }