This commit is contained in:
2023-12-01 13:44:58 +01:00
parent b958ff7ca2
commit 6e98701299
239 changed files with 827 additions and 102 deletions

47
api/handler/apiHandler.go Normal file
View File

@@ -0,0 +1,47 @@
package handler
import (
"gogs.mikescher.com/BlackForestBytes/goext/ginext"
bunny "locbunny"
"locbunny/logic"
"locbunny/models"
"net/http"
)
type APIHandler struct {
app *logic.Application
}
func NewAPIHandler(app *logic.Application) APIHandler {
return APIHandler{
app: app,
}
}
// ListServer swaggerdoc
//
// @Summary List running server
//
// @Success 200 {object} handler.ListServer.response
// @Failure 400 {object} models.APIError
// @Failure 500 {object} models.APIError
//
// @Router /server [GET]
func (h APIHandler) ListServer(pctx ginext.PreContext) ginext.HTTPResponse {
type response struct {
Server []models.Server `json:"server"`
}
ctx, _, errResp := pctx.Start()
if errResp != nil {
return *errResp
}
defer ctx.Cancel()
srvs, err := h.app.ListServer(ctx, bunny.Conf.VerifyConnTimeoutAPI)
if err != nil {
return ginext.Error(err)
}
return ginext.JSON(http.StatusOK, response{Server: srvs})
}

View File

@@ -1,11 +1,20 @@
package handler
import (
"bytes"
"context"
"encoding/json"
"github.com/gin-gonic/gin"
"gogs.mikescher.com/BlackForestBytes/goext/ginext"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
templhtml "html/template"
bunny "locbunny"
"locbunny/logic"
"locbunny/models"
"locbunny/webassets"
"net/http"
"path/filepath"
templtext "text/template"
"time"
)
type WebHandler struct {
@@ -18,32 +27,151 @@ func NewWebHandler(app *logic.Application) WebHandler {
}
}
// ListServer swaggerdoc
// ServeIndexHTML swaggerdoc
//
// @Summary List running server
// @Summary (Website)
//
// @Success 200 {object} handler.ListServer.response
// @Failure 400 {object} models.APIError
// @Failure 500 {object} models.APIError
//
// @Router /server [GET]
func (h WebHandler) ListServer(pctx ginext.PreContext) ginext.HTTPResponse {
type response struct {
Server []models.Server `json:"server"`
}
// @Router / [GET]
// @Router /index.html [GET]
func (h WebHandler) ServeIndexHTML(pctx ginext.PreContext) ginext.HTTPResponse {
ctx, _, errResp := pctx.Start()
if errResp != nil {
return *errResp
}
defer ctx.Cancel()
srvs, err := h.app.ListServer(ctx)
templ, err := h.app.Assets.Template("index.html", h.buildIndexHTMLTemplate)
if err != nil {
return ginext.Error(err)
}
langext.SortBy(srvs, func(v models.Server) int { return v.Port })
data := map[string]any{}
return ginext.JSON(http.StatusOK, response{Server: srvs})
bin := bytes.Buffer{}
err = templ.Execute(&bin, data)
if err != nil {
return ginext.Error(err)
}
return ginext.Data(http.StatusOK, "text/html", bin.Bytes())
}
// ServeScriptJS swaggerdoc
//
// @Summary (Website)
//
// @Router /scripts.script.js [GET]
func (h WebHandler) ServeScriptJS(pctx ginext.PreContext) ginext.HTTPResponse {
ctx, _, errResp := pctx.Start()
if errResp != nil {
return *errResp
}
defer ctx.Cancel()
templ, err := h.app.Assets.Template("scripts/script.js", h.buildScriptJSTemplate)
if err != nil {
return ginext.Error(err)
}
data := map[string]any{}
bin := bytes.Buffer{}
err = templ.Execute(&bin, data)
if err != nil {
return ginext.Error(err)
}
return ginext.Data(http.StatusOK, "text/javascript", bin.Bytes())
}
func (h WebHandler) buildIndexHTMLTemplate(content []byte) (webassets.ITemplate, error) {
t := templhtml.New("index.html")
t.Funcs(h.templateFuncMap())
_, err := t.Parse(string(content))
if err != nil {
return nil, err
}
return t, nil
}
func (h WebHandler) ServeAssets(pctx ginext.PreContext) ginext.HTTPResponse {
type uri struct {
FP1 *string `uri:"fp1"`
FP2 *string `uri:"fp2"`
FP3 *string `uri:"fp3"`
}
var u uri
ctx, _, errResp := pctx.URI(&u).Start()
if errResp != nil {
return *errResp
}
defer ctx.Cancel()
assetpath := ""
if u.FP1 == nil && u.FP2 == nil && u.FP3 == nil {
assetpath = filepath.Join()
} else if u.FP2 == nil && u.FP3 == nil {
assetpath = filepath.Join(*u.FP1)
} else if u.FP3 == nil {
assetpath = filepath.Join(*u.FP1, *u.FP2)
} else {
assetpath = filepath.Join(*u.FP1, *u.FP2, *u.FP3)
}
data, err := h.app.Assets.Read(assetpath)
if err != nil {
return ginext.JSON(http.StatusNotFound, gin.H{"error": "AssetNotFound", "assetpath": assetpath})
}
mime := bunny.FilenameToMime(assetpath, "text/plain")
return ginext.Data(http.StatusOK, mime, data)
}
func (h WebHandler) buildScriptJSTemplate(content []byte) (webassets.ITemplate, error) {
t := templtext.New("scripts/script.js")
t.Funcs(h.templateFuncMap())
_, err := t.Parse(string(content))
if err != nil {
return nil, err
}
return t, nil
}
func (h WebHandler) templateFuncMap() map[string]any {
return map[string]any{
"listServers": func() []models.Server {
ctx, cancel := context.WithTimeout(context.Background(), bunny.Conf.VerifyConnTimeoutHTML+2*time.Second)
defer cancel()
v, err := h.app.ListServer(ctx, bunny.Conf.VerifyConnTimeoutHTML)
if err != nil {
panic(err)
}
return v
},
"safe_html": func(s string) templhtml.HTML { return templhtml.HTML(s) }, //nolint:gosec
"safe_js": func(s string) templhtml.JS { return templhtml.JS(s) }, //nolint:gosec
"json": func(obj any) string {
v, err := json.Marshal(obj)
if err != nil {
panic(err)
}
return string(v)
},
"json_indent": func(obj any) string {
v, err := json.MarshalIndent(obj, "", " ")
if err != nil {
panic(err)
}
return string(v)
},
"mkarr": func(ln int) []int { return make([]int, ln) },
}
}

View File

@@ -13,6 +13,7 @@ type Router struct {
app *logic.Application
commonHandler handler.CommonHandler
apiHandler handler.APIHandler
webHandler handler.WebHandler
}
@@ -21,6 +22,7 @@ func NewRouter(app *logic.Application) *Router {
app: app,
commonHandler: handler.NewCommonHandler(app),
apiHandler: handler.NewAPIHandler(app),
webHandler: handler.NewWebHandler(app),
}
}
@@ -50,9 +52,18 @@ func (r *Router) Init(e *ginext.GinWrapper) {
docs.GET("/swagger/*sub").Handle(swagger.Handle)
}
// ================ Website ================
e.Routes().GET("/").Handle(r.webHandler.ServeIndexHTML)
e.Routes().GET("/index.html").Handle(r.webHandler.ServeIndexHTML)
e.Routes().GET("/scripts/script.js").Handle(r.webHandler.ServeScriptJS)
e.Routes().GET("/:fp1").Handle(r.webHandler.ServeAssets)
e.Routes().GET("/:fp1/:fp2").Handle(r.webHandler.ServeAssets)
e.Routes().GET("/:fp1/:fp2/:fp3").Handle(r.webHandler.ServeAssets)
// ================ API ================
api.GET("/server").Handle(r.webHandler.ListServer)
api.GET("/server").Handle(r.apiHandler.ListServer)
// ================ ================