headerscanner.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package fasthttp
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. )
  7. type headerScanner struct {
  8. initialized bool
  9. b []byte
  10. r int
  11. key []byte
  12. value []byte
  13. err error
  14. }
  15. func (s *headerScanner) next() bool {
  16. if !s.initialized {
  17. if bytes.HasPrefix(s.b, strCRLF) {
  18. s.r = 2
  19. return false
  20. }
  21. i := bytes.Index(s.b, strCRLFCRLF)
  22. if i < 0 {
  23. s.err = errNeedMore
  24. return false
  25. }
  26. i += 4
  27. s.b = s.b[:i]
  28. if len(s.b) > 0 && (s.b[0] == ' ' || s.b[0] == '\t') {
  29. s.err = errors.New("invalid headers, headers cannot start with space or tab")
  30. return false
  31. }
  32. s.initialized = true
  33. }
  34. kv, err := s.readContinuedLineSlice()
  35. if len(kv) == 0 {
  36. s.err = err
  37. return false
  38. }
  39. // Key ends at first colon.
  40. k, v, ok := bytes.Cut(kv, strColon)
  41. if !ok {
  42. s.err = fmt.Errorf("malformed MIME header line: %q", kv)
  43. return false
  44. }
  45. if !isValidHeaderKey(k) {
  46. s.err = fmt.Errorf("malformed MIME header line: %q", kv)
  47. return false
  48. }
  49. // Skip initial spaces in value.
  50. v = bytes.TrimLeft(v, " \t")
  51. s.key = k
  52. s.value = v
  53. if err != nil {
  54. s.err = err
  55. return false
  56. }
  57. return true
  58. }
  59. // readLine reads a line from b, starting at s.r, and returns it.
  60. func (s *headerScanner) readLine() (line []byte) {
  61. searchStart := 0
  62. for {
  63. if i := bytes.IndexByte(s.b[s.r+searchStart:], '\n'); i >= 0 {
  64. i += searchStart
  65. line = s.b[s.r : s.r+i+1]
  66. s.r += i + 1
  67. break
  68. }
  69. searchStart = len(s.b) - s.r
  70. }
  71. if len(line) == 0 {
  72. return
  73. }
  74. // drop \n and possible preceding \r
  75. if line[len(line)-1] == '\n' {
  76. drop := 1
  77. if len(line) > 1 && line[len(line)-2] == '\r' {
  78. drop = 2
  79. }
  80. line = line[:len(line)-drop]
  81. }
  82. return
  83. }
  84. // readContinuedLineSlice reads continued lines from b until it finds a line
  85. // that does not start with a space or tab, or it reaches the end of b.
  86. func (s *headerScanner) readContinuedLineSlice() ([]byte, error) {
  87. line := s.readLine()
  88. if len(line) == 0 { // blank line - no continuation
  89. return line, nil
  90. }
  91. if bytes.IndexByte(line, ':') < 0 {
  92. return nil, fmt.Errorf("malformed MIME header: missing colon: %q", line)
  93. }
  94. // If the line doesn't start with a space or tab, we are done.
  95. if len(s.b)-s.r > 1 {
  96. peek := s.b[s.r : s.r+2]
  97. if len(peek) > 0 && (isASCIILetter(peek[0]) || peek[0] == '\n') ||
  98. len(peek) == 2 && peek[0] == '\r' && peek[1] == '\n' {
  99. return trim(line), nil
  100. }
  101. }
  102. mline := trim(line)
  103. // Read continuation lines.
  104. for s.skipSpace() {
  105. mline = append(mline, ' ')
  106. line := s.readLine()
  107. mline = append(mline, trim(line)...)
  108. }
  109. return mline, nil
  110. }
  111. // skipSpace skips one or multiple spaces and tabs in b.
  112. func (s *headerScanner) skipSpace() bool {
  113. skipped := false
  114. for {
  115. c := s.b[s.r]
  116. if c != ' ' && c != '\t' {
  117. break
  118. }
  119. s.r++
  120. skipped = true
  121. }
  122. return skipped
  123. }
  124. func isASCIILetter(b byte) bool {
  125. b |= 0x20 // Make lower case.
  126. return 'a' <= b && b <= 'z'
  127. }
  128. // trim returns s with leading and trailing spaces and tabs removed.
  129. // It does not assume Unicode or UTF-8.
  130. func trim(s []byte) []byte {
  131. i := 0
  132. for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
  133. i++
  134. }
  135. n := len(s)
  136. for n > i && (s[n-1] == ' ' || s[n-1] == '\t') {
  137. n--
  138. }
  139. return s[i:n]
  140. }