Reload server and edit configuration. (#15)
The first iteration for config editor and server reload from the web interface.
This commit is contained in:
parent
56d32fd1f4
commit
0e2288565d
53 changed files with 882 additions and 178 deletions
87
http/api.go
Normal file
87
http/api.go
Normal file
|
@ -0,0 +1,87 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/ajnavarro/distribyted/config"
|
||||
"github.com/ajnavarro/distribyted/stats"
|
||||
"github.com/anacrolix/missinggo/v2/filecache"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var apiStatusHandler = func(fc *filecache.Cache, ss *stats.Torrent) gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
// TODO move to a struct
|
||||
ctx.JSON(200, gin.H{
|
||||
"cacheItems": fc.Info().NumItems,
|
||||
"cacheFilled": fc.Info().Filled / 1024 / 1024,
|
||||
"cacheCapacity": fc.Info().Capacity / 1024 / 1024,
|
||||
"torrentStats": ss.GlobalStats(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var apiRoutesHandler = func(ss *stats.Torrent) gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
stats := ss.RoutesStats()
|
||||
ctx.JSON(200, stats)
|
||||
}
|
||||
}
|
||||
|
||||
var apiGetConfigFile = func(ch *config.Handler) gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
rc, err := ch.GetRaw()
|
||||
if err != nil {
|
||||
ctx.AbortWithError(500, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data(200, "text/x-yaml", rc)
|
||||
}
|
||||
}
|
||||
|
||||
var apiSetConfigFile = func(ch *config.Handler) gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
if ctx.Request.Body == nil {
|
||||
ctx.AbortWithError(500, errors.New("no config file sent"))
|
||||
return
|
||||
}
|
||||
|
||||
c, err := ioutil.ReadAll(ctx.Request.Body)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(500, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(c) == 0 {
|
||||
ctx.AbortWithError(500, errors.New("no config file sent"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := ch.Set(c); err != nil {
|
||||
ctx.AbortWithError(500, err)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO return something?
|
||||
ctx.JSON(200, nil)
|
||||
}
|
||||
}
|
||||
|
||||
var apiReloadServer = func(ch *config.Handler) gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
ctx.Stream(func(w io.Writer) bool {
|
||||
err := ch.Reload(
|
||||
func(m string) {
|
||||
ctx.SSEvent("reload", m)
|
||||
})
|
||||
if err != nil {
|
||||
ctx.AbortWithError(500, err)
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
}
|
||||
}
|
52
http/http.go
Normal file
52
http/http.go
Normal file
|
@ -0,0 +1,52 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ajnavarro/distribyted"
|
||||
"github.com/ajnavarro/distribyted/config"
|
||||
"github.com/ajnavarro/distribyted/stats"
|
||||
"github.com/anacrolix/missinggo/v2/filecache"
|
||||
"github.com/gin-contrib/static"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/shurcooL/httpfs/html/vfstemplate"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func New(fc *filecache.Cache, ss *stats.Torrent, ch *config.Handler, port int) error {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
r := gin.New()
|
||||
r.Use(gin.Recovery())
|
||||
r.Use(gin.ErrorLogger())
|
||||
|
||||
assets := distribyted.NewBinaryFileSystem(distribyted.HttpFS, "/assets")
|
||||
r.Use(static.Serve("/assets", assets))
|
||||
t, err := vfstemplate.ParseGlob(distribyted.HttpFS, nil, "/templates/*")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing html: %w", err)
|
||||
}
|
||||
|
||||
r.SetHTMLTemplate(t)
|
||||
|
||||
r.GET("/", indexHandler)
|
||||
r.GET("/routes", routesHandler(ss))
|
||||
r.GET("/config", configHandler)
|
||||
|
||||
api := r.Group("/api")
|
||||
{
|
||||
api.GET("/status", apiStatusHandler(fc, ss))
|
||||
api.GET("/routes", apiRoutesHandler(ss))
|
||||
api.GET("/config", apiGetConfigFile(ch))
|
||||
api.POST("/config", apiSetConfigFile(ch))
|
||||
api.POST("/reload", apiReloadServer(ch))
|
||||
|
||||
}
|
||||
|
||||
logrus.WithField("host", fmt.Sprintf("0.0.0.0:%d", port)).Info("starting webserver")
|
||||
|
||||
if err := r.Run(fmt.Sprintf(":%d", port)); err != nil {
|
||||
return fmt.Errorf("error initializing server: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
22
http/web.go
Normal file
22
http/web.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/ajnavarro/distribyted/stats"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var indexHandler = func(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "index.html", nil)
|
||||
}
|
||||
|
||||
var routesHandler = func(ss *stats.Torrent) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "routes.html", ss.RoutesStats())
|
||||
}
|
||||
}
|
||||
|
||||
var configHandler = func(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "config.html", nil)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue