a simple url shortener in Go (check it out at qurl.org)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
3.3 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. package bolt
  2. import (
  3. "encoding/binary"
  4. "git.binarythought.com/cdramey/qurl/obj"
  5. )
  6. var (
  7. QURLBucket = []byte{0x00}
  8. ReverseBucket = []byte{0x01}
  9. URLField = []byte{0x00}
  10. CreatedField = []byte{0x01}
  11. IPField = []byte{0x02}
  12. BrowserField = []byte{0x03}
  13. )
  14. func (stor *BoltStorage) AddQURL(q *obj.QURL) error {
  15. tx, err := stor.DB.Begin(true)
  16. if err != nil {
  17. return err
  18. }
  19. defer tx.Rollback()
  20. rb, err := tx.CreateBucketIfNotExists(QURLBucket)
  21. if err != nil {
  22. return err
  23. }
  24. // Populate the ID from the sequence if we don't have one
  25. if q.ID == 0 {
  26. s, err := rb.NextSequence()
  27. if err != nil {
  28. return err
  29. }
  30. // Bolt's sequence starts at 1, so for
  31. // backwards compatibility we have subtract
  32. // one so we're zero-based
  33. q.ID = (s - 1)
  34. }
  35. // Create a byte array from the ID
  36. bid := make([]byte, 8)
  37. binary.BigEndian.PutUint64(bid, q.ID)
  38. // Add an entry into the reverse indexed bucket for quickly
  39. // determining if a URL is already in the database
  40. ab, err := tx.CreateBucketIfNotExists(ReverseBucket)
  41. if err != nil {
  42. return err
  43. }
  44. err = ab.Put([]byte(q.URL), bid)
  45. qb, err := rb.CreateBucketIfNotExists(bid)
  46. if err != nil {
  47. return err
  48. }
  49. // Write the ID to URL
  50. err = qb.Put(URLField, []byte(q.URL))
  51. if err != nil {
  52. return err
  53. }
  54. if !q.Created.IsZero() {
  55. // Create byte array from the Created date
  56. bdt, err := q.Created.MarshalBinary()
  57. if err != nil {
  58. return err
  59. }
  60. // Write the Created date
  61. err = qb.Put(CreatedField, bdt)
  62. if err != nil {
  63. return err
  64. }
  65. }
  66. if q.IP != nil {
  67. err = qb.Put(IPField, q.IP)
  68. if err != nil {
  69. return err
  70. }
  71. }
  72. if len(q.Browser) > 0 {
  73. err = qb.Put(BrowserField, []byte(q.Browser))
  74. if err != nil {
  75. return err
  76. }
  77. }
  78. if err := tx.Commit(); err != nil {
  79. return err
  80. }
  81. return nil
  82. }
  83. func (stor *BoltStorage) SetQURLSequence(seq uint64) error {
  84. tx, err := stor.DB.Begin(true)
  85. if err != nil {
  86. return err
  87. }
  88. defer tx.Rollback()
  89. qb, err := tx.CreateBucketIfNotExists(QURLBucket)
  90. if err != nil {
  91. return err
  92. }
  93. // Since the sequence number is decremented by one
  94. // for backwards compatibility (see above)
  95. // we increment it by one when setting the sequence
  96. qb.SetSequence(seq + 1)
  97. if err := tx.Commit(); err != nil {
  98. return err
  99. }
  100. return nil
  101. }
  102. func (stor *BoltStorage) GetQURLByURL(u string) (*obj.QURL, error) {
  103. tx, err := stor.DB.Begin(false)
  104. if err != nil {
  105. return nil, err
  106. }
  107. defer tx.Rollback()
  108. ab := tx.Bucket(ReverseBucket)
  109. if ab == nil {
  110. return nil, nil
  111. }
  112. bid := ab.Get([]byte(u))
  113. if bid == nil {
  114. return nil, nil
  115. }
  116. rb := tx.Bucket(QURLBucket)
  117. if rb == nil {
  118. return nil, nil
  119. }
  120. qb := rb.Bucket(bid)
  121. if qb == nil {
  122. return nil, nil
  123. }
  124. q := &obj.QURL{ID: binary.BigEndian.Uint64(bid)}
  125. qu := qb.Get(URLField)
  126. if qu != nil {
  127. q.URL = string(qu)
  128. }
  129. return q, nil
  130. }
  131. func (stor *BoltStorage) GetQURLByID(id uint64) (*obj.QURL, error) {
  132. tx, err := stor.DB.Begin(false)
  133. if err != nil {
  134. return nil, err
  135. }
  136. defer tx.Rollback()
  137. // Create a byte array from the ID
  138. bid := make([]byte, 8)
  139. binary.BigEndian.PutUint64(bid, id)
  140. rb := tx.Bucket(QURLBucket)
  141. if rb == nil {
  142. return nil, nil
  143. }
  144. qb := rb.Bucket(bid)
  145. if qb == nil {
  146. return nil, nil
  147. }
  148. q := &obj.QURL{ID: id}
  149. qu := qb.Get(URLField)
  150. if qu != nil {
  151. q.URL = string(qu)
  152. }
  153. return q, nil
  154. }