request.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package websocket
  2. import (
  3. "bytes"
  4. "fmt"
  5. "net/http"
  6. "strings"
  7. "go-common/app/service/main/broadcast/libs/bufio"
  8. )
  9. // Request request.
  10. type Request struct {
  11. Method string
  12. RequestURI string
  13. Proto string
  14. Host string
  15. Header http.Header
  16. reader *bufio.Reader
  17. }
  18. // ReadRequest reads and parses an incoming request from b.
  19. func ReadRequest(r *bufio.Reader) (req *Request, err error) {
  20. var (
  21. b []byte
  22. ok bool
  23. )
  24. req = &Request{reader: r}
  25. if b, err = req.readLine(); err != nil {
  26. return
  27. }
  28. if req.Method, req.RequestURI, req.Proto, ok = parseRequestLine(string(b)); !ok {
  29. return nil, fmt.Errorf("malformed HTTP request %s", b)
  30. }
  31. if req.Header, err = req.readMIMEHeader(); err != nil {
  32. return
  33. }
  34. req.Host = req.Header.Get("Host")
  35. return req, nil
  36. }
  37. func (r *Request) readLine() ([]byte, error) {
  38. var line []byte
  39. for {
  40. l, more, err := r.reader.ReadLine()
  41. if err != nil {
  42. return nil, err
  43. }
  44. // Avoid the copy if the first call produced a full line.
  45. if line == nil && !more {
  46. return l, nil
  47. }
  48. line = append(line, l...)
  49. if !more {
  50. break
  51. }
  52. }
  53. return line, nil
  54. }
  55. func (r *Request) readMIMEHeader() (header http.Header, err error) {
  56. var (
  57. line []byte
  58. i int
  59. k, v string
  60. )
  61. header = make(http.Header, 16)
  62. for {
  63. if line, err = r.readLine(); err != nil {
  64. return
  65. }
  66. line = trim(line)
  67. if len(line) == 0 {
  68. return
  69. }
  70. if i = bytes.IndexByte(line, ':'); i <= 0 {
  71. err = fmt.Errorf("malformed MIME header line: " + string(line))
  72. return
  73. }
  74. k = string(line[:i])
  75. // Skip initial spaces in value.
  76. i++ // skip colon
  77. for i < len(line) && (line[i] == ' ' || line[i] == '\t') {
  78. i++
  79. }
  80. v = string(line[i:])
  81. header.Add(k, v)
  82. }
  83. }
  84. // parseRequestLine parses "GET /foo HTTP/1.1" into its three parts.
  85. func parseRequestLine(line string) (method, requestURI, proto string, ok bool) {
  86. s1 := strings.Index(line, " ")
  87. s2 := strings.Index(line[s1+1:], " ")
  88. if s1 < 0 || s2 < 0 {
  89. return
  90. }
  91. s2 += s1 + 1
  92. return line[:s1], line[s1+1 : s2], line[s2+1:], true
  93. }
  94. // trim returns s with leading and trailing spaces and tabs removed.
  95. // It does not assume Unicode or UTF-8.
  96. func trim(s []byte) []byte {
  97. i := 0
  98. for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
  99. i++
  100. }
  101. n := len(s)
  102. for n > i && (s[n-1] == ' ' || s[n-1] == '\t') {
  103. n--
  104. }
  105. return s[i:n]
  106. }