head.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. package httphead
  2. import (
  3. "bufio"
  4. "bytes"
  5. )
  6. // Version contains protocol major and minor version.
  7. type Version struct {
  8. Major int
  9. Minor int
  10. }
  11. // RequestLine contains parameters parsed from the first request line.
  12. type RequestLine struct {
  13. Method []byte
  14. URI []byte
  15. Version Version
  16. }
  17. // ResponseLine contains parameters parsed from the first response line.
  18. type ResponseLine struct {
  19. Version Version
  20. Status int
  21. Reason []byte
  22. }
  23. // SplitRequestLine splits given slice of bytes into three chunks without
  24. // parsing.
  25. func SplitRequestLine(line []byte) (method, uri, version []byte) {
  26. return split3(line, ' ')
  27. }
  28. // ParseRequestLine parses http request line like "GET / HTTP/1.0".
  29. func ParseRequestLine(line []byte) (r RequestLine, ok bool) {
  30. var i int
  31. for i = 0; i < len(line); i++ {
  32. c := line[i]
  33. if !OctetTypes[c].IsToken() {
  34. if i > 0 && c == ' ' {
  35. break
  36. }
  37. return
  38. }
  39. }
  40. if i == len(line) {
  41. return
  42. }
  43. var proto []byte
  44. r.Method = line[:i]
  45. r.URI, proto = split2(line[i+1:], ' ')
  46. if len(r.URI) == 0 {
  47. return
  48. }
  49. if major, minor, ok := ParseVersion(proto); ok {
  50. r.Version.Major = major
  51. r.Version.Minor = minor
  52. return r, true
  53. }
  54. return r, false
  55. }
  56. // SplitResponseLine splits given slice of bytes into three chunks without
  57. // parsing.
  58. func SplitResponseLine(line []byte) (version, status, reason []byte) {
  59. return split3(line, ' ')
  60. }
  61. // ParseResponseLine parses first response line into ResponseLine struct.
  62. func ParseResponseLine(line []byte) (r ResponseLine, ok bool) {
  63. var (
  64. proto []byte
  65. status []byte
  66. )
  67. proto, status, r.Reason = split3(line, ' ')
  68. if major, minor, ok := ParseVersion(proto); ok {
  69. r.Version.Major = major
  70. r.Version.Minor = minor
  71. } else {
  72. return r, false
  73. }
  74. if n, ok := IntFromASCII(status); ok {
  75. r.Status = n
  76. } else {
  77. return r, false
  78. }
  79. // TODO(gobwas): parse here r.Reason fot TEXT rule:
  80. // TEXT = <any OCTET except CTLs,
  81. // but including LWS>
  82. return r, true
  83. }
  84. var (
  85. httpVersion10 = []byte("HTTP/1.0")
  86. httpVersion11 = []byte("HTTP/1.1")
  87. httpVersionPrefix = []byte("HTTP/")
  88. )
  89. // ParseVersion parses major and minor version of HTTP protocol.
  90. // It returns parsed values and true if parse is ok.
  91. func ParseVersion(bts []byte) (major, minor int, ok bool) {
  92. switch {
  93. case bytes.Equal(bts, httpVersion11):
  94. return 1, 1, true
  95. case bytes.Equal(bts, httpVersion10):
  96. return 1, 0, true
  97. case len(bts) < 8:
  98. return
  99. case !bytes.Equal(bts[:5], httpVersionPrefix):
  100. return
  101. }
  102. bts = bts[5:]
  103. dot := bytes.IndexByte(bts, '.')
  104. if dot == -1 {
  105. return
  106. }
  107. major, ok = IntFromASCII(bts[:dot])
  108. if !ok {
  109. return
  110. }
  111. minor, ok = IntFromASCII(bts[dot+1:])
  112. if !ok {
  113. return
  114. }
  115. return major, minor, true
  116. }
  117. // ReadLine reads line from br. It reads until '\n' and returns bytes without
  118. // '\n' or '\r\n' at the end.
  119. // It returns err if and only if line does not end in '\n'. Note that read
  120. // bytes returned in any case of error.
  121. //
  122. // It is much like the textproto/Reader.ReadLine() except the thing that it
  123. // returns raw bytes, instead of string. That is, it avoids copying bytes read
  124. // from br.
  125. //
  126. // textproto/Reader.ReadLineBytes() is also makes copy of resulting bytes to be
  127. // safe with future I/O operations on br.
  128. //
  129. // We could control I/O operations on br and do not need to make additional
  130. // copy for safety.
  131. func ReadLine(br *bufio.Reader) ([]byte, error) {
  132. var line []byte
  133. for {
  134. bts, err := br.ReadSlice('\n')
  135. if err == bufio.ErrBufferFull {
  136. // Copy bytes because next read will discard them.
  137. line = append(line, bts...)
  138. continue
  139. }
  140. // Avoid copy of single read.
  141. if line == nil {
  142. line = bts
  143. } else {
  144. line = append(line, bts...)
  145. }
  146. if err != nil {
  147. return line, err
  148. }
  149. // Size of line is at least 1.
  150. // In other case bufio.ReadSlice() returns error.
  151. n := len(line)
  152. // Cut '\n' or '\r\n'.
  153. if n > 1 && line[n-2] == '\r' {
  154. line = line[:n-2]
  155. } else {
  156. line = line[:n-1]
  157. }
  158. return line, nil
  159. }
  160. }
  161. // ParseHeaderLine parses HTTP header as key-value pair. It returns parsed
  162. // values and true if parse is ok.
  163. func ParseHeaderLine(line []byte) (k, v []byte, ok bool) {
  164. colon := bytes.IndexByte(line, ':')
  165. if colon == -1 {
  166. return
  167. }
  168. k = trim(line[:colon])
  169. for _, c := range k {
  170. if !OctetTypes[c].IsToken() {
  171. return nil, nil, false
  172. }
  173. }
  174. v = trim(line[colon+1:])
  175. return k, v, true
  176. }
  177. // IntFromASCII converts ascii encoded decimal numeric value from HTTP entities
  178. // to an integer.
  179. func IntFromASCII(bts []byte) (ret int, ok bool) {
  180. // ASCII numbers all start with the high-order bits 0011.
  181. // If you see that, and the next bits are 0-9 (0000 - 1001) you can grab those
  182. // bits and interpret them directly as an integer.
  183. var n int
  184. if n = len(bts); n < 1 {
  185. return 0, false
  186. }
  187. for i := 0; i < n; i++ {
  188. if bts[i]&0xf0 != 0x30 {
  189. return 0, false
  190. }
  191. ret += int(bts[i]&0xf) * pow(10, n-i-1)
  192. }
  193. return ret, true
  194. }
  195. const (
  196. toLower = 'a' - 'A' // for use with OR.
  197. toUpper = ^byte(toLower) // for use with AND.
  198. )
  199. // CanonicalizeHeaderKey is like standard textproto/CanonicalMIMEHeaderKey,
  200. // except that it operates with slice of bytes and modifies it inplace without
  201. // copying.
  202. func CanonicalizeHeaderKey(k []byte) {
  203. upper := true
  204. for i, c := range k {
  205. if upper && 'a' <= c && c <= 'z' {
  206. k[i] &= toUpper
  207. } else if !upper && 'A' <= c && c <= 'Z' {
  208. k[i] |= toLower
  209. }
  210. upper = c == '-'
  211. }
  212. }
  213. // pow for integers implementation.
  214. // See Donald Knuth, The Art of Computer Programming, Volume 2, Section 4.6.3
  215. func pow(a, b int) int {
  216. p := 1
  217. for b > 0 {
  218. if b&1 != 0 {
  219. p *= a
  220. }
  221. b >>= 1
  222. a *= a
  223. }
  224. return p
  225. }
  226. func split3(p []byte, sep byte) (p1, p2, p3 []byte) {
  227. a := bytes.IndexByte(p, sep)
  228. b := bytes.IndexByte(p[a+1:], sep)
  229. if a == -1 || b == -1 {
  230. return p, nil, nil
  231. }
  232. b += a + 1
  233. return p[:a], p[a+1 : b], p[b+1:]
  234. }
  235. func split2(p []byte, sep byte) (p1, p2 []byte) {
  236. i := bytes.IndexByte(p, sep)
  237. if i == -1 {
  238. return p, nil
  239. }
  240. return p[:i], p[i+1:]
  241. }
  242. func trim(p []byte) []byte {
  243. var i, j int
  244. for i = 0; i < len(p) && (p[i] == ' ' || p[i] == '\t'); {
  245. i++
  246. }
  247. for j = len(p); j > i && (p[j-1] == ' ' || p[j-1] == '\t'); {
  248. j--
  249. }
  250. return p[i:j]
  251. }