httphead.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. // Package httphead contains utils for parsing HTTP and HTTP-grammar compatible
  2. // text protocols headers.
  3. //
  4. // That is, this package first aim is to bring ability to easily parse
  5. // constructions, described here https://tools.ietf.org/html/rfc2616#section-2
  6. package httphead
  7. import (
  8. "bytes"
  9. "strings"
  10. )
  11. // ScanTokens parses data in this form:
  12. //
  13. // list = 1#token
  14. //
  15. // It returns false if data is malformed.
  16. func ScanTokens(data []byte, it func([]byte) bool) bool {
  17. lexer := &Scanner{data: data}
  18. var ok bool
  19. for lexer.Next() {
  20. switch lexer.Type() {
  21. case ItemToken:
  22. ok = true
  23. if !it(lexer.Bytes()) {
  24. return true
  25. }
  26. case ItemSeparator:
  27. if !isComma(lexer.Bytes()) {
  28. return false
  29. }
  30. default:
  31. return false
  32. }
  33. }
  34. return ok && !lexer.err
  35. }
  36. // ParseOptions parses all header options and appends it to given slice of
  37. // Option. It returns flag of successful (wellformed input) parsing.
  38. //
  39. // Note that appended options are all consist of subslices of data. That is,
  40. // mutation of data will mutate appended options.
  41. func ParseOptions(data []byte, options []Option) ([]Option, bool) {
  42. var i int
  43. index := -1
  44. return options, ScanOptions(data, func(idx int, name, attr, val []byte) Control {
  45. if idx != index {
  46. index = idx
  47. i = len(options)
  48. options = append(options, Option{Name: name})
  49. }
  50. if attr != nil {
  51. options[i].Parameters.Set(attr, val)
  52. }
  53. return ControlContinue
  54. })
  55. }
  56. // SelectFlag encodes way of options selection.
  57. type SelectFlag byte
  58. // String represetns flag as string.
  59. func (f SelectFlag) String() string {
  60. var flags [2]string
  61. var n int
  62. if f&SelectCopy != 0 {
  63. flags[n] = "copy"
  64. n++
  65. }
  66. if f&SelectUnique != 0 {
  67. flags[n] = "unique"
  68. n++
  69. }
  70. return "[" + strings.Join(flags[:n], "|") + "]"
  71. }
  72. const (
  73. // SelectCopy causes selector to copy selected option before appending it
  74. // to resulting slice.
  75. // If SelectCopy flag is not passed to selector, then appended options will
  76. // contain sub-slices of the initial data.
  77. SelectCopy SelectFlag = 1 << iota
  78. // SelectUnique causes selector to append only not yet existing option to
  79. // resulting slice. Unique is checked by comparing option names.
  80. SelectUnique
  81. )
  82. // OptionSelector contains configuration for selecting Options from header value.
  83. type OptionSelector struct {
  84. // Check is a filter function that applied to every Option that possibly
  85. // could be selected.
  86. // If Check is nil all options will be selected.
  87. Check func(Option) bool
  88. // Flags contains flags for options selection.
  89. Flags SelectFlag
  90. // Alloc used to allocate slice of bytes when selector is configured with
  91. // SelectCopy flag. It will be called with number of bytes needed for copy
  92. // of single Option.
  93. // If Alloc is nil make is used.
  94. Alloc func(n int) []byte
  95. }
  96. // Select parses header data and appends it to given slice of Option.
  97. // It also returns flag of successful (wellformed input) parsing.
  98. func (s OptionSelector) Select(data []byte, options []Option) ([]Option, bool) {
  99. var current Option
  100. var has bool
  101. index := -1
  102. alloc := s.Alloc
  103. if alloc == nil {
  104. alloc = defaultAlloc
  105. }
  106. check := s.Check
  107. if check == nil {
  108. check = defaultCheck
  109. }
  110. ok := ScanOptions(data, func(idx int, name, attr, val []byte) Control {
  111. if idx != index {
  112. if has && check(current) {
  113. if s.Flags&SelectCopy != 0 {
  114. current = current.Copy(alloc(current.Size()))
  115. }
  116. options = append(options, current)
  117. has = false
  118. }
  119. if s.Flags&SelectUnique != 0 {
  120. for i := len(options) - 1; i >= 0; i-- {
  121. if bytes.Equal(options[i].Name, name) {
  122. return ControlSkip
  123. }
  124. }
  125. }
  126. index = idx
  127. current = Option{Name: name}
  128. has = true
  129. }
  130. if attr != nil {
  131. current.Parameters.Set(attr, val)
  132. }
  133. return ControlContinue
  134. })
  135. if has && check(current) {
  136. if s.Flags&SelectCopy != 0 {
  137. current = current.Copy(alloc(current.Size()))
  138. }
  139. options = append(options, current)
  140. }
  141. return options, ok
  142. }
  143. func defaultAlloc(n int) []byte { return make([]byte, n) }
  144. func defaultCheck(Option) bool { return true }
  145. // Control represents operation that scanner should perform.
  146. type Control byte
  147. const (
  148. // ControlContinue causes scanner to continue scan tokens.
  149. ControlContinue Control = iota
  150. // ControlBreak causes scanner to stop scan tokens.
  151. ControlBreak
  152. // ControlSkip causes scanner to skip current entity.
  153. ControlSkip
  154. )
  155. // ScanOptions parses data in this form:
  156. //
  157. // values = 1#value
  158. // value = token *( ";" param )
  159. // param = token [ "=" (token | quoted-string) ]
  160. //
  161. // It calls given callback with the index of the option, option itself and its
  162. // parameter (attribute and its value, both could be nil). Index is useful when
  163. // header contains multiple choises for the same named option.
  164. //
  165. // Given callback should return one of the defined Control* values.
  166. // ControlSkip means that passed key is not in caller's interest. That is, all
  167. // parameters of that key will be skipped.
  168. // ControlBreak means that no more keys and parameters should be parsed. That
  169. // is, it must break parsing immediately.
  170. // ControlContinue means that caller want to receive next parameter and its
  171. // value or the next key.
  172. //
  173. // It returns false if data is malformed.
  174. func ScanOptions(data []byte, it func(index int, option, attribute, value []byte) Control) bool {
  175. lexer := &Scanner{data: data}
  176. var ok bool
  177. var state int
  178. const (
  179. stateKey = iota
  180. stateParamBeforeName
  181. stateParamName
  182. stateParamBeforeValue
  183. stateParamValue
  184. )
  185. var (
  186. index int
  187. key, param, value []byte
  188. mustCall bool
  189. )
  190. for lexer.Next() {
  191. var (
  192. call bool
  193. growIndex int
  194. )
  195. t := lexer.Type()
  196. v := lexer.Bytes()
  197. switch t {
  198. case ItemToken:
  199. switch state {
  200. case stateKey, stateParamBeforeName:
  201. key = v
  202. state = stateParamBeforeName
  203. mustCall = true
  204. case stateParamName:
  205. param = v
  206. state = stateParamBeforeValue
  207. mustCall = true
  208. case stateParamValue:
  209. value = v
  210. state = stateParamBeforeName
  211. call = true
  212. default:
  213. return false
  214. }
  215. case ItemString:
  216. if state != stateParamValue {
  217. return false
  218. }
  219. value = v
  220. state = stateParamBeforeName
  221. call = true
  222. case ItemSeparator:
  223. switch {
  224. case isComma(v) && state == stateKey:
  225. // Nothing to do.
  226. case isComma(v) && state == stateParamBeforeName:
  227. state = stateKey
  228. // Make call only if we have not called this key yet.
  229. call = mustCall
  230. if !call {
  231. // If we have already called callback with the key
  232. // that just ended.
  233. index++
  234. } else {
  235. // Else grow the index after calling callback.
  236. growIndex = 1
  237. }
  238. case isComma(v) && state == stateParamBeforeValue:
  239. state = stateKey
  240. growIndex = 1
  241. call = true
  242. case isSemicolon(v) && state == stateParamBeforeName:
  243. state = stateParamName
  244. case isSemicolon(v) && state == stateParamBeforeValue:
  245. state = stateParamName
  246. call = true
  247. case isEquality(v) && state == stateParamBeforeValue:
  248. state = stateParamValue
  249. default:
  250. return false
  251. }
  252. default:
  253. return false
  254. }
  255. if call {
  256. switch it(index, key, param, value) {
  257. case ControlBreak:
  258. // User want to stop to parsing parameters.
  259. return true
  260. case ControlSkip:
  261. // User want to skip current param.
  262. state = stateKey
  263. lexer.SkipEscaped(',')
  264. case ControlContinue:
  265. // User is interested in rest of parameters.
  266. // Nothing to do.
  267. default:
  268. panic("unexpected control value")
  269. }
  270. ok = true
  271. param = nil
  272. value = nil
  273. mustCall = false
  274. index += growIndex
  275. }
  276. }
  277. if mustCall {
  278. ok = true
  279. it(index, key, param, value)
  280. }
  281. return ok && !lexer.err
  282. }
  283. func isComma(b []byte) bool {
  284. return len(b) == 1 && b[0] == ','
  285. }
  286. func isSemicolon(b []byte) bool {
  287. return len(b) == 1 && b[0] == ';'
  288. }
  289. func isEquality(b []byte) bool {
  290. return len(b) == 1 && b[0] == '='
  291. }