tstor/http/api.go
Antonio Navarro Perez ddda39b22a
Server implementation. (#90)
* Server implementation.

- Share the content of a folder as a magnet file.
- Web interface with all data needed for sharing data.
- New configuration to add several servers
- Every time the content of the server folder is changed, the magnet
file will be generated again.

Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>

* Update dependencies

Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>

* Use boltdb piece completion storage.

Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
2021-11-21 14:03:18 +01:00

122 lines
2.7 KiB
Go

package http
import (
"bytes"
"io"
"math"
"net/http"
"os"
"sort"
"github.com/anacrolix/missinggo/v2/filecache"
"github.com/distribyted/distribyted/torrent"
"github.com/gin-gonic/gin"
)
var apiStatusHandler = func(fc *filecache.Cache, ss *torrent.Stats) gin.HandlerFunc {
return func(ctx *gin.Context) {
// TODO move to a struct
ctx.JSON(http.StatusOK, gin.H{
"cacheItems": fc.Info().NumItems,
"cacheFilled": fc.Info().Filled / 1024 / 1024,
"cacheCapacity": fc.Info().Capacity / 1024 / 1024,
"torrentStats": ss.GlobalStats(),
})
}
}
var apiServersHandler = func(ss []*torrent.Server) gin.HandlerFunc {
return func(ctx *gin.Context) {
var infos []*torrent.ServerInfo
for _, s := range ss {
infos = append(infos, s.Info())
}
ctx.JSON(http.StatusOK, infos)
}
}
var apiRoutesHandler = func(ss *torrent.Stats) gin.HandlerFunc {
return func(ctx *gin.Context) {
s := ss.RoutesStats()
sort.Sort(torrent.ByName(s))
ctx.JSON(http.StatusOK, s)
}
}
var apiAddTorrentHandler = func(s *torrent.Service) gin.HandlerFunc {
return func(ctx *gin.Context) {
route := ctx.Param("route")
var json RouteAdd
if err := ctx.ShouldBindJSON(&json); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := s.AddMagnet(route, json.Magnet); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, nil)
}
}
var apiDelTorrentHandler = func(s *torrent.Service) gin.HandlerFunc {
return func(ctx *gin.Context) {
route := ctx.Param("route")
hash := ctx.Param("torrent_hash")
if err := s.RemoveFromHash(route, hash); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, nil)
}
}
var apiLogHandler = func(path string) gin.HandlerFunc {
return func(ctx *gin.Context) {
f, err := os.Open(path)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
fi, err := f.Stat()
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
max := math.Max(float64(-fi.Size()), -1024*8*8)
_, err = f.Seek(int64(max), os.SEEK_END)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
var b bytes.Buffer
ctx.Stream(func(w io.Writer) bool {
_, err := b.ReadFrom(f)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return false
}
_, err = b.WriteTo(w)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return false
}
return true
})
if err := f.Close(); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
}
}