package web import ( _ "embed" "fmt" "html/template" "net/http" "path/filepath" "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" csrf "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, renderer *template.Template, storeSecret, csrfSecret []byte) *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))) // Back done, front WIP r.GET("/queue/:name", makeQueueHandler(rd)) // JSON done r.GET("/", makeHomeHandler(rd)) // TODO r.GET("/queue/:name/confirm", mw, makeConfirmHandler()) r.POST("/queue/:name/delete", mw, makeDeleteConfirmHandler(rd)) r.GET("/queue/:name/purge", mw, makePurgeHandler(rd)) r.POST("/queue/:name/purge", mw, makePurgeConfirmHandler(rd)) r.POST("/queue/:name/redrive", mw, makeRedriveHandler(rd)) return r } func HttpService(dic *izidic.Container) (any, error) { csrfSecret := dic.MustParam(services.PCSRFSecret).([]byte) storeSecret := dic.MustParam(services.PStoreSecret).([]byte) rd := dic.MustService(services.SvcRedriver).(redriver.Redriver) re := dic.MustService(services.SvcRenderer).(*template.Template) return SetupRoutes(rd, re, storeSecret, csrfSecret), nil } func RendererService(_ *izidic.Container) (any, error) { var err error renderer := template.New("redriver").Funcs(template.FuncMap{ "dump": func(args ...any) template.HTML { return "
" + template.HTML(spew.Sdump(args...)) + "\n" }, }) for _, tpl := range []struct { name string value string }{ {"confirm", front.Confirm}, {"flashes", front.Flashes}, {"queue-get", front.QueueGet}, {"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)) }