args.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. package fasthttp
  2. import (
  3. "bytes"
  4. "errors"
  5. "io"
  6. "sort"
  7. "sync"
  8. "github.com/valyala/bytebufferpool"
  9. )
  10. const (
  11. argsNoValue = true
  12. argsHasValue = false
  13. )
  14. // AcquireArgs returns an empty Args object from the pool.
  15. //
  16. // The returned Args may be returned to the pool with ReleaseArgs
  17. // when no longer needed. This allows reducing GC load.
  18. func AcquireArgs() *Args {
  19. return argsPool.Get().(*Args)
  20. }
  21. // ReleaseArgs returns the object acquired via AcquireArgs to the pool.
  22. //
  23. // Do not access the released Args object, otherwise data races may occur.
  24. func ReleaseArgs(a *Args) {
  25. a.Reset()
  26. argsPool.Put(a)
  27. }
  28. var argsPool = &sync.Pool{
  29. New: func() interface{} {
  30. return &Args{}
  31. },
  32. }
  33. // Args represents query arguments.
  34. //
  35. // It is forbidden copying Args instances. Create new instances instead
  36. // and use CopyTo().
  37. //
  38. // Args instance MUST NOT be used from concurrently running goroutines.
  39. type Args struct {
  40. noCopy noCopy //nolint:unused,structcheck
  41. args []argsKV
  42. buf []byte
  43. }
  44. type argsKV struct {
  45. key []byte
  46. value []byte
  47. noValue bool
  48. }
  49. // Reset clears query args.
  50. func (a *Args) Reset() {
  51. a.args = a.args[:0]
  52. }
  53. // CopyTo copies all args to dst.
  54. func (a *Args) CopyTo(dst *Args) {
  55. dst.Reset()
  56. dst.args = copyArgs(dst.args, a.args)
  57. }
  58. // VisitAll calls f for each existing arg.
  59. //
  60. // f must not retain references to key and value after returning.
  61. // Make key and/or value copies if you need storing them after returning.
  62. func (a *Args) VisitAll(f func(key, value []byte)) {
  63. visitArgs(a.args, f)
  64. }
  65. // Len returns the number of query args.
  66. func (a *Args) Len() int {
  67. return len(a.args)
  68. }
  69. // Parse parses the given string containing query args.
  70. func (a *Args) Parse(s string) {
  71. a.buf = append(a.buf[:0], s...)
  72. a.ParseBytes(a.buf)
  73. }
  74. // ParseBytes parses the given b containing query args.
  75. func (a *Args) ParseBytes(b []byte) {
  76. a.Reset()
  77. var s argsScanner
  78. s.b = b
  79. var kv *argsKV
  80. a.args, kv = allocArg(a.args)
  81. for s.next(kv) {
  82. if len(kv.key) > 0 || len(kv.value) > 0 {
  83. a.args, kv = allocArg(a.args)
  84. }
  85. }
  86. a.args = releaseArg(a.args)
  87. }
  88. // String returns string representation of query args.
  89. func (a *Args) String() string {
  90. return string(a.QueryString())
  91. }
  92. // QueryString returns query string for the args.
  93. //
  94. // The returned value is valid until the Args is reused or released (ReleaseArgs).
  95. // Do not store references to the returned value. Make copies instead.
  96. func (a *Args) QueryString() []byte {
  97. a.buf = a.AppendBytes(a.buf[:0])
  98. return a.buf
  99. }
  100. // Sort sorts Args by key and then value using 'f' as comparison function.
  101. //
  102. // For example args.Sort(bytes.Compare)
  103. func (a *Args) Sort(f func(x, y []byte) int) {
  104. sort.SliceStable(a.args, func(i, j int) bool {
  105. n := f(a.args[i].key, a.args[j].key)
  106. if n == 0 {
  107. return f(a.args[i].value, a.args[j].value) == -1
  108. }
  109. return n == -1
  110. })
  111. }
  112. // AppendBytes appends query string to dst and returns the extended dst.
  113. func (a *Args) AppendBytes(dst []byte) []byte {
  114. for i, n := 0, len(a.args); i < n; i++ {
  115. kv := &a.args[i]
  116. dst = AppendQuotedArg(dst, kv.key)
  117. if !kv.noValue {
  118. dst = append(dst, '=')
  119. if len(kv.value) > 0 {
  120. dst = AppendQuotedArg(dst, kv.value)
  121. }
  122. }
  123. if i+1 < n {
  124. dst = append(dst, '&')
  125. }
  126. }
  127. return dst
  128. }
  129. // WriteTo writes query string to w.
  130. //
  131. // WriteTo implements io.WriterTo interface.
  132. func (a *Args) WriteTo(w io.Writer) (int64, error) {
  133. n, err := w.Write(a.QueryString())
  134. return int64(n), err
  135. }
  136. // Del deletes argument with the given key from query args.
  137. func (a *Args) Del(key string) {
  138. a.args = delAllArgs(a.args, key)
  139. }
  140. // DelBytes deletes argument with the given key from query args.
  141. func (a *Args) DelBytes(key []byte) {
  142. a.args = delAllArgs(a.args, b2s(key))
  143. }
  144. // Add adds 'key=value' argument.
  145. //
  146. // Multiple values for the same key may be added.
  147. func (a *Args) Add(key, value string) {
  148. a.args = appendArg(a.args, key, value, argsHasValue)
  149. }
  150. // AddBytesK adds 'key=value' argument.
  151. //
  152. // Multiple values for the same key may be added.
  153. func (a *Args) AddBytesK(key []byte, value string) {
  154. a.args = appendArg(a.args, b2s(key), value, argsHasValue)
  155. }
  156. // AddBytesV adds 'key=value' argument.
  157. //
  158. // Multiple values for the same key may be added.
  159. func (a *Args) AddBytesV(key string, value []byte) {
  160. a.args = appendArg(a.args, key, b2s(value), argsHasValue)
  161. }
  162. // AddBytesKV adds 'key=value' argument.
  163. //
  164. // Multiple values for the same key may be added.
  165. func (a *Args) AddBytesKV(key, value []byte) {
  166. a.args = appendArg(a.args, b2s(key), b2s(value), argsHasValue)
  167. }
  168. // AddNoValue adds only 'key' as argument without the '='.
  169. //
  170. // Multiple values for the same key may be added.
  171. func (a *Args) AddNoValue(key string) {
  172. a.args = appendArg(a.args, key, "", argsNoValue)
  173. }
  174. // AddBytesKNoValue adds only 'key' as argument without the '='.
  175. //
  176. // Multiple values for the same key may be added.
  177. func (a *Args) AddBytesKNoValue(key []byte) {
  178. a.args = appendArg(a.args, b2s(key), "", argsNoValue)
  179. }
  180. // Set sets 'key=value' argument.
  181. func (a *Args) Set(key, value string) {
  182. a.args = setArg(a.args, key, value, argsHasValue)
  183. }
  184. // SetBytesK sets 'key=value' argument.
  185. func (a *Args) SetBytesK(key []byte, value string) {
  186. a.args = setArg(a.args, b2s(key), value, argsHasValue)
  187. }
  188. // SetBytesV sets 'key=value' argument.
  189. func (a *Args) SetBytesV(key string, value []byte) {
  190. a.args = setArg(a.args, key, b2s(value), argsHasValue)
  191. }
  192. // SetBytesKV sets 'key=value' argument.
  193. func (a *Args) SetBytesKV(key, value []byte) {
  194. a.args = setArgBytes(a.args, key, value, argsHasValue)
  195. }
  196. // SetNoValue sets only 'key' as argument without the '='.
  197. //
  198. // Only key in argument, like key1&key2
  199. func (a *Args) SetNoValue(key string) {
  200. a.args = setArg(a.args, key, "", argsNoValue)
  201. }
  202. // SetBytesKNoValue sets 'key' argument.
  203. func (a *Args) SetBytesKNoValue(key []byte) {
  204. a.args = setArg(a.args, b2s(key), "", argsNoValue)
  205. }
  206. // Peek returns query arg value for the given key.
  207. //
  208. // The returned value is valid until the Args is reused or released (ReleaseArgs).
  209. // Do not store references to the returned value. Make copies instead.
  210. func (a *Args) Peek(key string) []byte {
  211. return peekArgStr(a.args, key)
  212. }
  213. // PeekBytes returns query arg value for the given key.
  214. //
  215. // The returned value is valid until the Args is reused or released (ReleaseArgs).
  216. // Do not store references to the returned value. Make copies instead.
  217. func (a *Args) PeekBytes(key []byte) []byte {
  218. return peekArgBytes(a.args, key)
  219. }
  220. // PeekMulti returns all the arg values for the given key.
  221. func (a *Args) PeekMulti(key string) [][]byte {
  222. var values [][]byte
  223. a.VisitAll(func(k, v []byte) {
  224. if string(k) == key {
  225. values = append(values, v)
  226. }
  227. })
  228. return values
  229. }
  230. // PeekMultiBytes returns all the arg values for the given key.
  231. func (a *Args) PeekMultiBytes(key []byte) [][]byte {
  232. return a.PeekMulti(b2s(key))
  233. }
  234. // Has returns true if the given key exists in Args.
  235. func (a *Args) Has(key string) bool {
  236. return hasArg(a.args, key)
  237. }
  238. // HasBytes returns true if the given key exists in Args.
  239. func (a *Args) HasBytes(key []byte) bool {
  240. return hasArg(a.args, b2s(key))
  241. }
  242. // ErrNoArgValue is returned when Args value with the given key is missing.
  243. var ErrNoArgValue = errors.New("no Args value for the given key")
  244. // GetUint returns uint value for the given key.
  245. func (a *Args) GetUint(key string) (int, error) {
  246. value := a.Peek(key)
  247. if len(value) == 0 {
  248. return -1, ErrNoArgValue
  249. }
  250. return ParseUint(value)
  251. }
  252. // SetUint sets uint value for the given key.
  253. func (a *Args) SetUint(key string, value int) {
  254. bb := bytebufferpool.Get()
  255. bb.B = AppendUint(bb.B[:0], value)
  256. a.SetBytesV(key, bb.B)
  257. bytebufferpool.Put(bb)
  258. }
  259. // SetUintBytes sets uint value for the given key.
  260. func (a *Args) SetUintBytes(key []byte, value int) {
  261. a.SetUint(b2s(key), value)
  262. }
  263. // GetUintOrZero returns uint value for the given key.
  264. //
  265. // Zero (0) is returned on error.
  266. func (a *Args) GetUintOrZero(key string) int {
  267. n, err := a.GetUint(key)
  268. if err != nil {
  269. n = 0
  270. }
  271. return n
  272. }
  273. // GetUfloat returns ufloat value for the given key.
  274. func (a *Args) GetUfloat(key string) (float64, error) {
  275. value := a.Peek(key)
  276. if len(value) == 0 {
  277. return -1, ErrNoArgValue
  278. }
  279. return ParseUfloat(value)
  280. }
  281. // GetUfloatOrZero returns ufloat value for the given key.
  282. //
  283. // Zero (0) is returned on error.
  284. func (a *Args) GetUfloatOrZero(key string) float64 {
  285. f, err := a.GetUfloat(key)
  286. if err != nil {
  287. f = 0
  288. }
  289. return f
  290. }
  291. // GetBool returns boolean value for the given key.
  292. //
  293. // true is returned for "1", "t", "T", "true", "TRUE", "True", "y", "yes", "Y", "YES", "Yes",
  294. // otherwise false is returned.
  295. func (a *Args) GetBool(key string) bool {
  296. switch string(a.Peek(key)) {
  297. // Support the same true cases as strconv.ParseBool
  298. // See: https://github.com/golang/go/blob/4e1b11e2c9bdb0ddea1141eed487be1a626ff5be/src/strconv/atob.go#L12
  299. // and Y and Yes versions.
  300. case "1", "t", "T", "true", "TRUE", "True", "y", "yes", "Y", "YES", "Yes":
  301. return true
  302. default:
  303. return false
  304. }
  305. }
  306. func visitArgs(args []argsKV, f func(k, v []byte)) {
  307. for i, n := 0, len(args); i < n; i++ {
  308. kv := &args[i]
  309. f(kv.key, kv.value)
  310. }
  311. }
  312. func visitArgsKey(args []argsKV, f func(k []byte)) {
  313. for i, n := 0, len(args); i < n; i++ {
  314. kv := &args[i]
  315. f(kv.key)
  316. }
  317. }
  318. func copyArgs(dst, src []argsKV) []argsKV {
  319. if cap(dst) < len(src) {
  320. tmp := make([]argsKV, len(src))
  321. dst = dst[:cap(dst)] // copy all of dst.
  322. copy(tmp, dst)
  323. for i := len(dst); i < len(tmp); i++ {
  324. // Make sure nothing is nil.
  325. tmp[i].key = []byte{}
  326. tmp[i].value = []byte{}
  327. }
  328. dst = tmp
  329. }
  330. n := len(src)
  331. dst = dst[:n]
  332. for i := 0; i < n; i++ {
  333. dstKV := &dst[i]
  334. srcKV := &src[i]
  335. dstKV.key = append(dstKV.key[:0], srcKV.key...)
  336. if srcKV.noValue {
  337. dstKV.value = dstKV.value[:0]
  338. } else {
  339. dstKV.value = append(dstKV.value[:0], srcKV.value...)
  340. }
  341. dstKV.noValue = srcKV.noValue
  342. }
  343. return dst
  344. }
  345. func delAllArgsBytes(args []argsKV, key []byte) []argsKV {
  346. return delAllArgs(args, b2s(key))
  347. }
  348. func delAllArgs(args []argsKV, key string) []argsKV {
  349. for i, n := 0, len(args); i < n; i++ {
  350. kv := &args[i]
  351. if key == string(kv.key) {
  352. tmp := *kv
  353. copy(args[i:], args[i+1:])
  354. n--
  355. i--
  356. args[n] = tmp
  357. args = args[:n]
  358. }
  359. }
  360. return args
  361. }
  362. func setArgBytes(h []argsKV, key, value []byte, noValue bool) []argsKV {
  363. return setArg(h, b2s(key), b2s(value), noValue)
  364. }
  365. func setArg(h []argsKV, key, value string, noValue bool) []argsKV {
  366. n := len(h)
  367. for i := 0; i < n; i++ {
  368. kv := &h[i]
  369. if key == string(kv.key) {
  370. if noValue {
  371. kv.value = kv.value[:0]
  372. } else {
  373. kv.value = append(kv.value[:0], value...)
  374. }
  375. kv.noValue = noValue
  376. return h
  377. }
  378. }
  379. return appendArg(h, key, value, noValue)
  380. }
  381. func appendArgBytes(h []argsKV, key, value []byte, noValue bool) []argsKV {
  382. return appendArg(h, b2s(key), b2s(value), noValue)
  383. }
  384. func appendArg(args []argsKV, key, value string, noValue bool) []argsKV {
  385. var kv *argsKV
  386. args, kv = allocArg(args)
  387. kv.key = append(kv.key[:0], key...)
  388. if noValue {
  389. kv.value = kv.value[:0]
  390. } else {
  391. kv.value = append(kv.value[:0], value...)
  392. }
  393. kv.noValue = noValue
  394. return args
  395. }
  396. func allocArg(h []argsKV) ([]argsKV, *argsKV) {
  397. n := len(h)
  398. if cap(h) > n {
  399. h = h[:n+1]
  400. } else {
  401. h = append(h, argsKV{
  402. value: []byte{},
  403. })
  404. }
  405. return h, &h[n]
  406. }
  407. func releaseArg(h []argsKV) []argsKV {
  408. return h[:len(h)-1]
  409. }
  410. func hasArg(h []argsKV, key string) bool {
  411. for i, n := 0, len(h); i < n; i++ {
  412. kv := &h[i]
  413. if key == string(kv.key) {
  414. return true
  415. }
  416. }
  417. return false
  418. }
  419. func peekArgBytes(h []argsKV, k []byte) []byte {
  420. for i, n := 0, len(h); i < n; i++ {
  421. kv := &h[i]
  422. if bytes.Equal(kv.key, k) {
  423. return kv.value
  424. }
  425. }
  426. return nil
  427. }
  428. func peekArgStr(h []argsKV, k string) []byte {
  429. for i, n := 0, len(h); i < n; i++ {
  430. kv := &h[i]
  431. if string(kv.key) == k {
  432. return kv.value
  433. }
  434. }
  435. return nil
  436. }
  437. type argsScanner struct {
  438. b []byte
  439. }
  440. func (s *argsScanner) next(kv *argsKV) bool {
  441. if len(s.b) == 0 {
  442. return false
  443. }
  444. kv.noValue = argsHasValue
  445. isKey := true
  446. k := 0
  447. for i, c := range s.b {
  448. switch c {
  449. case '=':
  450. if isKey {
  451. isKey = false
  452. kv.key = decodeArgAppend(kv.key[:0], s.b[:i])
  453. k = i + 1
  454. }
  455. case '&':
  456. if isKey {
  457. kv.key = decodeArgAppend(kv.key[:0], s.b[:i])
  458. kv.value = kv.value[:0]
  459. kv.noValue = argsNoValue
  460. } else {
  461. kv.value = decodeArgAppend(kv.value[:0], s.b[k:i])
  462. }
  463. s.b = s.b[i+1:]
  464. return true
  465. }
  466. }
  467. if isKey {
  468. kv.key = decodeArgAppend(kv.key[:0], s.b)
  469. kv.value = kv.value[:0]
  470. kv.noValue = argsNoValue
  471. } else {
  472. kv.value = decodeArgAppend(kv.value[:0], s.b[k:])
  473. }
  474. s.b = s.b[len(s.b):]
  475. return true
  476. }
  477. func decodeArgAppend(dst, src []byte) []byte {
  478. idxPercent := bytes.IndexByte(src, '%')
  479. idxPlus := bytes.IndexByte(src, '+')
  480. if idxPercent == -1 && idxPlus == -1 {
  481. // fast path: src doesn't contain encoded chars
  482. return append(dst, src...)
  483. }
  484. idx := 0
  485. if idxPercent == -1 {
  486. idx = idxPlus
  487. } else if idxPlus == -1 {
  488. idx = idxPercent
  489. } else if idxPercent > idxPlus {
  490. idx = idxPlus
  491. } else {
  492. idx = idxPercent
  493. }
  494. dst = append(dst, src[:idx]...)
  495. // slow path
  496. for i := idx; i < len(src); i++ {
  497. c := src[i]
  498. if c == '%' {
  499. if i+2 >= len(src) {
  500. return append(dst, src[i:]...)
  501. }
  502. x2 := hex2intTable[src[i+2]]
  503. x1 := hex2intTable[src[i+1]]
  504. if x1 == 16 || x2 == 16 {
  505. dst = append(dst, '%')
  506. } else {
  507. dst = append(dst, x1<<4|x2)
  508. i += 2
  509. }
  510. } else if c == '+' {
  511. dst = append(dst, ' ')
  512. } else {
  513. dst = append(dst, c)
  514. }
  515. }
  516. return dst
  517. }
  518. // decodeArgAppendNoPlus is almost identical to decodeArgAppend, but it doesn't
  519. // substitute '+' with ' '.
  520. //
  521. // The function is copy-pasted from decodeArgAppend due to the performance
  522. // reasons only.
  523. func decodeArgAppendNoPlus(dst, src []byte) []byte {
  524. idx := bytes.IndexByte(src, '%')
  525. if idx < 0 {
  526. // fast path: src doesn't contain encoded chars
  527. return append(dst, src...)
  528. } else {
  529. dst = append(dst, src[:idx]...)
  530. }
  531. // slow path
  532. for i := idx; i < len(src); i++ {
  533. c := src[i]
  534. if c == '%' {
  535. if i+2 >= len(src) {
  536. return append(dst, src[i:]...)
  537. }
  538. x2 := hex2intTable[src[i+2]]
  539. x1 := hex2intTable[src[i+1]]
  540. if x1 == 16 || x2 == 16 {
  541. dst = append(dst, '%')
  542. } else {
  543. dst = append(dst, x1<<4|x2)
  544. i += 2
  545. }
  546. } else {
  547. dst = append(dst, c)
  548. }
  549. }
  550. return dst
  551. }
  552. func peekAllArgBytesToDst(dst [][]byte, h []argsKV, k []byte) [][]byte {
  553. for i, n := 0, len(h); i < n; i++ {
  554. kv := &h[i]
  555. if bytes.Equal(kv.key, k) {
  556. dst = append(dst, kv.value)
  557. }
  558. }
  559. return dst
  560. }