bytes_content_range.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package httptoo
  2. import (
  3. "fmt"
  4. "math"
  5. "regexp"
  6. "strconv"
  7. "strings"
  8. )
  9. type BytesContentRange struct {
  10. First, Last, Length int64
  11. }
  12. type BytesRange struct {
  13. First, Last int64
  14. }
  15. func (me BytesRange) String() string {
  16. if me.Last == math.MaxInt64 {
  17. return fmt.Sprintf("bytes=%d-", me.First)
  18. }
  19. return fmt.Sprintf("bytes=%d-%d", me.First, me.Last)
  20. }
  21. var (
  22. httpBytesRangeRegexp = regexp.MustCompile(`bytes[ =](\d+)-(\d*)`)
  23. )
  24. func ParseBytesRange(s string) (ret BytesRange, ok bool) {
  25. ss := httpBytesRangeRegexp.FindStringSubmatch(s)
  26. if ss == nil {
  27. return
  28. }
  29. var err error
  30. ret.First, err = strconv.ParseInt(ss[1], 10, 64)
  31. if err != nil {
  32. return
  33. }
  34. if ss[2] == "" {
  35. ret.Last = math.MaxInt64
  36. } else {
  37. ret.Last, err = strconv.ParseInt(ss[2], 10, 64)
  38. if err != nil {
  39. return
  40. }
  41. }
  42. ok = true
  43. return
  44. }
  45. func parseUnitRanges(s string) (unit, ranges string) {
  46. s = strings.TrimSpace(s)
  47. i := strings.IndexAny(s, " =")
  48. if i == -1 {
  49. return
  50. }
  51. unit = s[:i]
  52. ranges = s[i+1:]
  53. return
  54. }
  55. func parseFirstLast(s string) (first, last int64) {
  56. ss := strings.SplitN(s, "-", 2)
  57. first, err := strconv.ParseInt(ss[0], 10, 64)
  58. if err != nil {
  59. panic(err)
  60. }
  61. last, err = strconv.ParseInt(ss[1], 10, 64)
  62. if err != nil {
  63. panic(err)
  64. }
  65. return
  66. }
  67. func parseContentRange(s string) (ret BytesContentRange) {
  68. ss := strings.SplitN(s, "/", 2)
  69. firstLast := strings.TrimSpace(ss[0])
  70. if firstLast == "*" {
  71. ret.First = -1
  72. ret.Last = -1
  73. } else {
  74. ret.First, ret.Last = parseFirstLast(firstLast)
  75. }
  76. il := strings.TrimSpace(ss[1])
  77. if il == "*" {
  78. ret.Length = -1
  79. } else {
  80. var err error
  81. ret.Length, err = strconv.ParseInt(il, 10, 64)
  82. if err != nil {
  83. panic(err)
  84. }
  85. }
  86. return
  87. }
  88. func ParseBytesContentRange(s string) (ret BytesContentRange, ok bool) {
  89. unit, ranges := parseUnitRanges(s)
  90. if unit != "bytes" {
  91. return
  92. }
  93. ret = parseContentRange(ranges)
  94. ok = true
  95. return
  96. }