handlers.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package main
  2. import (
  3. "encoding/base64"
  4. "time"
  5. "github.com/gin-gonic/gin"
  6. )
  7. const defaultTTL = time.Hour * 24 * 365 // 默认过期时间,1年
  8. const defaultRenewTime = time.Hour * 48 // 默认续命时间,2天
  9. const defaultShortKeyLength = 7 // 默认短链接长度,7位
  10. // ShortToLongHandler gets the long URL from a short URL
  11. func ShortToLongHandler() gin.HandlerFunc {
  12. return func(c *gin.Context) {
  13. resp := Response{}
  14. shortKey := c.Param("shortKey")
  15. longURL := ShortToLong(c, shortKey)
  16. if longURL == "" {
  17. resp.Code = ResponseCodeServerError
  18. resp.Msg = "failed to get long URL, please check the short URL if exists or expired"
  19. c.JSON(404, resp)
  20. return
  21. }
  22. // todo
  23. // check whether need renew expiration time
  24. // only renew once per day
  25. // if err := Renew(c, shortKey, defaultRenewTime); err != nil {
  26. // logger.Warn("failed to renew short URL: ", err.Error())
  27. // }
  28. c.Redirect(301, longURL)
  29. }
  30. }
  31. type LongToShortParams struct {
  32. LongUrl string `form:"longUrl" json:"longUrl" binding:"required"`
  33. ShortKey string `form:"shortKey" json:"shortKey" binding:"omitempty"`
  34. }
  35. // LongToShortHandler creates a short URL from a long URL
  36. func LongToShortHandler() gin.HandlerFunc {
  37. return func(c *gin.Context) {
  38. resp := Response{}
  39. // check parameters
  40. req := LongToShortParams{}
  41. if err := c.ShouldBind(&req); err != nil {
  42. resp.Code = ResponseCodeParamsCheckError
  43. resp.Msg = "invalid parameters"
  44. logger.Warn("invalid parameters: ", err.Error())
  45. c.JSON(200, resp)
  46. return
  47. }
  48. // 兼容以前的实现,这里如果是 base64 编码的字符串,进行解码
  49. _longUrl, err := base64.StdEncoding.DecodeString(req.LongUrl)
  50. if err == nil {
  51. req.LongUrl = string(_longUrl)
  52. }
  53. // generate short key
  54. if req.ShortKey == "" {
  55. req.ShortKey = GenerateRandomString(defaultShortKeyLength)
  56. }
  57. // check whether short key exists
  58. exists, err := CheckRedisKeyIfExist(c, req.ShortKey)
  59. if err != nil {
  60. resp.Code = ResponseCodeServerError
  61. resp.Msg = "failed to check short key"
  62. logger.Error("failed to check short key: ", err.Error())
  63. c.JSON(200, resp)
  64. return
  65. }
  66. if exists {
  67. resp.Code = ResponseCodeParamsCheckError
  68. resp.Msg = "short key already exists, please use another one or leave it empty to generate automatically"
  69. logger.Info("short key already exists: ", req.ShortKey)
  70. c.JSON(200, resp)
  71. return
  72. }
  73. options := &LongToShortOptions{
  74. ShortKey: req.ShortKey,
  75. URL: req.LongUrl,
  76. expiration: defaultTTL,
  77. }
  78. if err := LongToShort(c, options); err != nil {
  79. resp.Code = ResponseCodeServerError
  80. resp.Msg = "failed to create short URL"
  81. logger.Warn("failed to create short URL: ", err.Error())
  82. c.JSON(200, resp)
  83. return
  84. }
  85. shortURL := proto + "://" + domain + "/" + options.ShortKey
  86. // 兼容以前的返回结构体
  87. respDataLegacy := gin.H{
  88. "Code": ResponseCodeSuccessLegacy,
  89. "ShortUrl": shortURL,
  90. }
  91. c.JSON(200, respDataLegacy)
  92. }
  93. }