routes.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package web
  2. import (
  3. _ "embed"
  4. "fmt"
  5. "html/template"
  6. "net/http"
  7. "path/filepath"
  8. "github.com/davecgh/go-spew/spew"
  9. "github.com/fgm/izidic"
  10. "github.com/gin-contrib/sessions"
  11. "github.com/gin-contrib/sessions/cookie"
  12. "github.com/gin-gonic/gin"
  13. csrf "github.com/utrack/gin-csrf"
  14. "code.osinet.fr/fgm/sqs_demo/back/services"
  15. "code.osinet.fr/fgm/sqs_demo/back/services/redriver"
  16. "code.osinet.fr/fgm/sqs_demo/front"
  17. )
  18. func SetupRoutes(rd redriver.Redriver, renderer *template.Template, storeSecret, csrfSecret []byte) *gin.Engine {
  19. const assetsPrefix = "/assets/"
  20. r := gin.Default()
  21. r.SetHTMLTemplate(renderer)
  22. _ = r.SetTrustedProxies(nil)
  23. store := cookie.NewStore(storeSecret)
  24. r.Use(sessions.Sessions("defaultsession", store))
  25. mw := csrf.Middleware(csrf.Options{
  26. Secret: string(csrfSecret),
  27. ErrorFunc: func(c *gin.Context) {
  28. c.String(http.StatusBadRequest, "CSRF token does not match")
  29. c.Abort()
  30. },
  31. TokenGetter: nil,
  32. })
  33. // Done
  34. r.StaticFS(assetsPrefix, PrefixFileSystem(assetsPrefix, http.FS(front.Assets)))
  35. r.GET("/queue", gin.WrapH(http.RedirectHandler("/", http.StatusMovedPermanently)))
  36. // Back done, front WIP
  37. r.GET("/queue/:name", makeQueueHandler(rd))
  38. // JSON done
  39. r.GET("/", makeHomeHandler(rd))
  40. // TODO
  41. r.GET("/queue/:name/confirm", mw, makeConfirmHandler())
  42. r.POST("/queue/:name/delete", mw, makeDeleteConfirmHandler(rd))
  43. r.GET("/queue/:name/purge", mw, makePurgeHandler(rd))
  44. r.POST("/queue/:name/purge", mw, makePurgeConfirmHandler(rd))
  45. r.POST("/queue/:name/redrive", mw, makeRedriveHandler(rd))
  46. return r
  47. }
  48. func HttpService(dic *izidic.Container) (any, error) {
  49. csrfSecret := dic.MustParam(services.PCSRFSecret).([]byte)
  50. storeSecret := dic.MustParam(services.PStoreSecret).([]byte)
  51. rd := dic.MustService(services.SvcRedriver).(redriver.Redriver)
  52. re := dic.MustService(services.SvcRenderer).(*template.Template)
  53. return SetupRoutes(rd, re, storeSecret, csrfSecret), nil
  54. }
  55. func RendererService(_ *izidic.Container) (any, error) {
  56. var err error
  57. renderer := template.New("redriver").Funcs(template.FuncMap{
  58. "dump": func(args ...any) template.HTML {
  59. return "<pre>" + template.HTML(spew.Sdump(args...)) + "</pre>\n"
  60. },
  61. })
  62. for _, tpl := range []struct {
  63. name string
  64. value string
  65. }{
  66. {"confirm", front.Confirm},
  67. {"flashes", front.Flashes},
  68. {"queue-get", front.QueueGet},
  69. {"500", front.Err500},
  70. } {
  71. renderer, err = renderer.New(tpl.name).Parse(tpl.value)
  72. if err != nil {
  73. return nil, fmt.Errorf("failed parsing %q template: %w", tpl.name, err)
  74. }
  75. }
  76. return renderer, nil
  77. }
  78. // PrefixFileSystem converts a http.FileSystem by serving it requests prefixed
  79. // by the passed prefix, allowing rooted static directories matching the name
  80. // of an embed.FS.
  81. func PrefixFileSystem(prefix string, ifs http.FileSystem) http.FileSystem {
  82. return &prefixedFS{
  83. prefix: prefix,
  84. ifs: ifs,
  85. }
  86. }
  87. type prefixedFS struct {
  88. prefix string
  89. ifs http.FileSystem
  90. }
  91. // Open implements http.FileSystem
  92. func (pfs *prefixedFS) Open(name string) (http.File, error) {
  93. return pfs.ifs.Open(filepath.Join(pfs.prefix, name))
  94. }