123 lines
3.2 KiB
Go
123 lines
3.2 KiB
Go
package helpers
|
|
|
|
import (
|
|
"embed"
|
|
"fmt"
|
|
"io/fs"
|
|
"net/http"
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gin-contrib/static"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/labstack/echo"
|
|
)
|
|
|
|
func SetCorsAndNoCacheHeaders() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
|
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
|
|
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
|
|
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
|
|
|
|
if c.Request.Method == "OPTIONS" {
|
|
c.AbortWithStatus(204)
|
|
return
|
|
}
|
|
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
type embedFileSystem struct {
|
|
http.FileSystem
|
|
indexes bool
|
|
}
|
|
|
|
func (e embedFileSystem) Exists(_ string, path string) bool {
|
|
f, err := e.Open(path)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
// check if indexing is allowed
|
|
s, _ := f.Stat()
|
|
if s.IsDir() && !e.indexes {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func EmbedFolder(fsEmbed embed.FS, targetPath string, index bool) static.ServeFileSystem {
|
|
subFS, err := fs.Sub(fsEmbed, targetPath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return embedFileSystem{
|
|
FileSystem: http.FS(subFS),
|
|
indexes: index,
|
|
}
|
|
}
|
|
|
|
func SendSong(ctx echo.Context, Filename string) error {
|
|
fmt.Println("Client requests: " + Filename)
|
|
|
|
//Check if file exists and open
|
|
openFile, err := os.Open(Filename)
|
|
if err != nil {
|
|
//File not found, send 404
|
|
//http.Error(ctx.Writer, "Song not found.", 404)
|
|
return ctx.String(http.StatusNotFound, "Song not found.")
|
|
}
|
|
defer func(openFile *os.File) {
|
|
_ = openFile.Close()
|
|
}(openFile) //Close after function return
|
|
|
|
//File is found, create and send the correct headers
|
|
|
|
//Get the Content-Type of the file
|
|
//Create a buffer to store the header of the file in
|
|
FileHeader := make([]byte, 512)
|
|
//Copy the headers into the FileHeader buffer
|
|
_, _ = openFile.Read(FileHeader)
|
|
//Get content type of file
|
|
//FileContentType := http.DetectContentType(FileHeader)
|
|
|
|
//Get the file size
|
|
FileStat, _ := openFile.Stat() //Get info from file
|
|
FileSize := strconv.FormatInt(FileStat.Size(), 10) //Get file size as a string
|
|
|
|
//Send the headers
|
|
//writer.Header().Set("Content-Disposition", "attachment; filename="+Filename)
|
|
ctx.Response().Header().Set("Content-Type", "audio/mpeg")
|
|
ctx.Response().Header().Set("Content-Length", FileSize)
|
|
ctx.Response().Header().Set("Expires", "Tue, 03 Jul 2001 06:00:00 GMT")
|
|
ctx.Response().Header().Set("Last-Modified", time.Now().String()+" GMT")
|
|
ctx.Response().Header().Set("Cache-Control", "no-cache, no-store, private, max-age=0")
|
|
ctx.Response().Header().Set("Pragma", "no-cache")
|
|
ctx.Response().Header().Set("X-Accel-Expires", "0")
|
|
|
|
var etagHeaders = []string{
|
|
"ETag",
|
|
"If-Modified-Since",
|
|
"If-Match",
|
|
"If-None-Match",
|
|
"If-Range",
|
|
"If-Unmodified-Since",
|
|
}
|
|
|
|
for _, v := range etagHeaders {
|
|
if ctx.Request().Header.Get(v) != "" {
|
|
ctx.Request().Header.Del(v)
|
|
}
|
|
}
|
|
|
|
//Send the file
|
|
//We read 512 bytes from the file already, so we reset the offset back to 0
|
|
_, _ = openFile.Seek(0, 0)
|
|
//_, _ = io.Copy(ctx.Writer, openFile) //'Copy' the file to the client
|
|
return ctx.Stream(http.StatusOK, "audio/mpeg", openFile)
|
|
}
|