post_target.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package ui
  2. import (
  3. "fmt"
  4. "io"
  5. "log"
  6. "net/http"
  7. "strings"
  8. kurzi18n "code.osinet.fr/fgm/kurz/web/i18n"
  9. i18n "github.com/nicksnyder/go-i18n/v2/i18n"
  10. "github.com/gorilla/sessions"
  11. "code.osinet.fr/fgm/kurz/domain"
  12. "github.com/gorilla/mux"
  13. )
  14. // handlePostTarget handles form POST requests to /
  15. func handlePostTarget(w http.ResponseWriter, r *http.Request, router *mux.Router) {
  16. var sess *sessions.Session
  17. sess, storeErr := store.Get(r, globals.SessionName)
  18. if storeErr != nil {
  19. log.Fatal()
  20. w.WriteHeader(http.StatusInternalServerError)
  21. return
  22. }
  23. r.ParseForm()
  24. defer r.Body.Close()
  25. rawTarget := r.PostForm.Get(rootInputName)
  26. localizer := kurzi18n.Localizer(r)
  27. target, err := validateTarget(rawTarget, localizer)
  28. if err != nil {
  29. sess.AddFlash(err.Error())
  30. sess.Save(r, w)
  31. location, err := URLFromRoute(router, RouteGetRoot, nil)
  32. if err != nil {
  33. w.WriteHeader(http.StatusInternalServerError)
  34. return
  35. }
  36. w.Header().Set("Location", location)
  37. w.WriteHeader(http.StatusSeeOther)
  38. return
  39. }
  40. short, isNew, err := domain.GetShortURL(target, localizer)
  41. if err != nil {
  42. w.WriteHeader(http.StatusInternalServerError)
  43. return
  44. }
  45. fqsu, err := URLFromRoute(router, RouteGetShort, map[string]string{"short": short})
  46. if err != nil {
  47. w.WriteHeader(http.StatusInternalServerError)
  48. return
  49. }
  50. sw := &strings.Builder{}
  51. var templateName string
  52. if isNew {
  53. templateName = "201"
  54. } else {
  55. templateName = "409"
  56. }
  57. defer sess.Save(r, w)
  58. data := struct {
  59. Flashes []interface{}
  60. FullyQualifiedShortURL string
  61. FullyQualifiedTargetURL string
  62. Globals
  63. }{
  64. sess.Flashes(),
  65. fqsu,
  66. target,
  67. globals,
  68. }
  69. err = tmpl.ExecuteTemplate(sw, templateName, data)
  70. if err != nil {
  71. fmt.Println(err)
  72. w.WriteHeader(http.StatusInternalServerError)
  73. return
  74. }
  75. if isNew {
  76. w.WriteHeader(http.StatusCreated)
  77. } else {
  78. w.WriteHeader(http.StatusConflict)
  79. }
  80. io.Copy(w, strings.NewReader(sw.String()))
  81. }
  82. func validateTarget(raw string, localizer *i18n.Localizer) (string, error) {
  83. if raw == "" {
  84. detail := localizer.MustLocalize(&i18n.LocalizeConfig{
  85. DefaultMessage: &i18n.Message{
  86. ID: "web.ui.empty.target",
  87. Other: "empty target",
  88. },
  89. })
  90. return "", domain.MakeError(localizer, domain.TargetInvalid.ID, detail)
  91. }
  92. // BUG(fgm): needs much more validation, starting with XSS.
  93. return raw, nil
  94. }