118 lines
3.5 KiB
Go
118 lines
3.5 KiB
Go
package web
|
|
|
|
import (
|
|
_ "embed"
|
|
"fmt"
|
|
"html/template"
|
|
"net/http"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/Masterminds/sprig/v3"
|
|
"github.com/davecgh/go-spew/spew"
|
|
"github.com/fgm/izidic"
|
|
"github.com/gin-contrib/sessions"
|
|
"github.com/gin-contrib/sessions/cookie"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/utrack/gin-csrf"
|
|
|
|
"code.osinet.fr/fgm/sqs_demo/back/services"
|
|
"code.osinet.fr/fgm/sqs_demo/back/services/redriver"
|
|
"code.osinet.fr/fgm/sqs_demo/front"
|
|
)
|
|
|
|
func SetupRoutes(rd redriver.Redriver, ms redriver.MessageStore, renderer *template.Template, storeSecret, csrfSecret []byte, prefix string) *gin.Engine {
|
|
const assetsPrefix = "/assets/"
|
|
r := gin.Default()
|
|
r.SetHTMLTemplate(renderer)
|
|
_ = r.SetTrustedProxies(nil)
|
|
store := cookie.NewStore(storeSecret)
|
|
r.Use(sessions.Sessions("defaultsession", store))
|
|
mw := csrf.Middleware(csrf.Options{
|
|
Secret: string(csrfSecret),
|
|
ErrorFunc: func(c *gin.Context) {
|
|
c.String(http.StatusBadRequest, "CSRF token does not match")
|
|
c.Abort()
|
|
},
|
|
TokenGetter: nil,
|
|
})
|
|
|
|
// Done
|
|
r.StaticFS(assetsPrefix, PrefixFileSystem(assetsPrefix, http.FS(front.Assets)))
|
|
r.GET("/queue", gin.WrapH(http.RedirectHandler("/", http.StatusMovedPermanently)))
|
|
r.GET("/queue/:name/confirm", mw, makeConfirmHandler()) // Needs mw to set token.
|
|
|
|
// Back done, front WIP
|
|
r.GET("/queue/:name", makeQueueHandler(rd, ms))
|
|
|
|
// JSON done
|
|
r.GET("/", makeHomeHandler(rd, prefix))
|
|
|
|
// TODO
|
|
r.POST("/queue/:name/delete", mw, makeDeleteHandler(rd)) // Needs mw to check token.
|
|
r.POST("/queue/:name/purge", mw, makePurgeHandler(rd)) // Needs mw to check token.
|
|
r.POST("/queue/:name/redrive", mw, makeRedriveHandler(rd, ms)) // Needs mw to check token.
|
|
return r
|
|
}
|
|
|
|
func HttpService(dic *izidic.Container) (any, error) {
|
|
csrfSecret := dic.MustParam(services.PCSRFSecret).([]byte)
|
|
prefix := dic.MustParam(services.PPrefix).(string)
|
|
storeSecret := dic.MustParam(services.PStoreSecret).([]byte)
|
|
|
|
rd := dic.MustService(services.SvcRedriver).(redriver.Redriver)
|
|
re := dic.MustService(services.SvcRenderer).(*template.Template)
|
|
ms := dic.MustService(services.SvcMessageStore).(redriver.MessageStore)
|
|
|
|
return SetupRoutes(rd, ms, re, storeSecret, csrfSecret, prefix), nil
|
|
}
|
|
|
|
func RendererService(_ *izidic.Container) (any, error) {
|
|
var err error
|
|
renderer := template.New("redriver").Funcs(template.FuncMap{
|
|
"dump": func(args ...any) template.HTML {
|
|
return "<pre>" + template.HTML(spew.Sdump(args...)) + "</pre>\n"
|
|
},
|
|
"timestamp": func(ts int64) time.Time {
|
|
return time.Unix(ts, 0)
|
|
},
|
|
"nameFromARN": redriver.NameFromARNString,
|
|
}).Funcs(sprig.FuncMap())
|
|
for _, tpl := range []struct {
|
|
name string
|
|
value string
|
|
}{
|
|
{"confirm", front.Confirm},
|
|
{"flashes", front.Flashes},
|
|
{"home", front.Home},
|
|
{"queue-get", front.QueueGet}, // Includes queue-item.
|
|
{"500", front.Err500},
|
|
} {
|
|
renderer, err = renderer.New(tpl.name).Parse(tpl.value)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed parsing %q template: %w", tpl.name, err)
|
|
}
|
|
}
|
|
|
|
return renderer, nil
|
|
}
|
|
|
|
// PrefixFileSystem converts a http.FileSystem by serving it requests prefixed
|
|
// by the passed prefix, allowing rooted static directories matching the name
|
|
// of an embed.FS.
|
|
func PrefixFileSystem(prefix string, ifs http.FileSystem) http.FileSystem {
|
|
return &prefixedFS{
|
|
prefix: prefix,
|
|
ifs: ifs,
|
|
}
|
|
}
|
|
|
|
type prefixedFS struct {
|
|
prefix string
|
|
ifs http.FileSystem
|
|
}
|
|
|
|
// Open implements http.FileSystem
|
|
func (pfs *prefixedFS) Open(name string) (http.File, error) {
|
|
return pfs.ifs.Open(filepath.Join(pfs.prefix, name))
|
|
}
|