upgrader.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. package wsutil
  2. import (
  3. "bufio"
  4. "bytes"
  5. "io"
  6. "io/ioutil"
  7. "net/http"
  8. "github.com/gobwas/ws"
  9. )
  10. // DebugUpgrader is a wrapper around ws.Upgrader. It tracks I/O of a
  11. // WebSocket handshake.
  12. //
  13. // Note that it must not be used in production applications that requires
  14. // Upgrade() to be efficient.
  15. type DebugUpgrader struct {
  16. // Upgrader contains upgrade to WebSocket options.
  17. Upgrader ws.Upgrader
  18. // OnRequest and OnResponse are the callbacks that will be called with the
  19. // HTTP request and response respectively.
  20. OnRequest, OnResponse func([]byte)
  21. }
  22. // Upgrade calls Upgrade() on underlying ws.Upgrader and tracks I/O on conn.
  23. func (d *DebugUpgrader) Upgrade(conn io.ReadWriter) (hs ws.Handshake, err error) {
  24. var (
  25. // Take the Reader and Writer parts from conn to be probably replaced
  26. // below.
  27. r io.Reader = conn
  28. w io.Writer = conn
  29. )
  30. if onRequest := d.OnRequest; onRequest != nil {
  31. var buf bytes.Buffer
  32. // First, we must read the entire request.
  33. req, err := http.ReadRequest(bufio.NewReader(
  34. io.TeeReader(conn, &buf),
  35. ))
  36. if err == nil {
  37. // Fulfill the buffer with the response body.
  38. io.Copy(ioutil.Discard, req.Body)
  39. req.Body.Close()
  40. }
  41. onRequest(buf.Bytes())
  42. r = io.MultiReader(
  43. &buf, conn,
  44. )
  45. }
  46. if onResponse := d.OnResponse; onResponse != nil {
  47. var buf bytes.Buffer
  48. // Intercept the response stream written by the Upgrade().
  49. w = io.MultiWriter(
  50. conn, &buf,
  51. )
  52. defer func() {
  53. onResponse(buf.Bytes())
  54. }()
  55. }
  56. return d.Upgrader.Upgrade(struct {
  57. io.Reader
  58. io.Writer
  59. }{r, w})
  60. }