gock.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. package gock
  2. import (
  3. "net/http"
  4. "net/url"
  5. "regexp"
  6. "sync"
  7. )
  8. // mutex is used interally for locking thread-sensitive functions.
  9. var mutex = &sync.Mutex{}
  10. // config global singleton store.
  11. var config = struct {
  12. Networking bool
  13. NetworkingFilters []FilterRequestFunc
  14. }{}
  15. // track unmatched requests so they can be tested for
  16. var unmatchedRequests = []*http.Request{}
  17. // New creates and registers a new HTTP mock with
  18. // default settings and returns the Request DSL for HTTP mock
  19. // definition and set up.
  20. func New(uri string) *Request {
  21. Intercept()
  22. res := NewResponse()
  23. req := NewRequest()
  24. req.URLStruct, res.Error = url.Parse(normalizeURI(uri))
  25. // Create the new mock expectation
  26. exp := NewMock(req, res)
  27. Register(exp)
  28. return req
  29. }
  30. // Intercepting returns true if gock is currently able to intercept.
  31. func Intercepting() bool {
  32. return http.DefaultTransport == DefaultTransport
  33. }
  34. // Intercept enables HTTP traffic interception via http.DefaultTransport.
  35. // If you are using a custom HTTP transport, you have to use `gock.Transport()`
  36. func Intercept() {
  37. if !Intercepting() {
  38. http.DefaultTransport = DefaultTransport
  39. }
  40. }
  41. // InterceptClient allows the developer to intercept HTTP traffic using
  42. // a custom http.Client who uses a non default http.Transport/http.RoundTripper implementation.
  43. func InterceptClient(cli *http.Client) {
  44. trans := NewTransport()
  45. trans.Transport = cli.Transport
  46. cli.Transport = trans
  47. }
  48. // RestoreClient allows the developer to disable and restore the
  49. // original transport in the given http.Client.
  50. func RestoreClient(cli *http.Client) {
  51. trans, ok := cli.Transport.(*Transport)
  52. if !ok {
  53. return
  54. }
  55. cli.Transport = trans.Transport
  56. }
  57. // Disable disables HTTP traffic interception by gock.
  58. func Disable() {
  59. mutex.Lock()
  60. defer mutex.Unlock()
  61. http.DefaultTransport = NativeTransport
  62. }
  63. // Off disables the default HTTP interceptors and removes
  64. // all the registered mocks, even if they has not been intercepted yet.
  65. func Off() {
  66. Flush()
  67. Disable()
  68. }
  69. // OffAll is like `Off()`, but it also removes the unmatched requests registry.
  70. func OffAll() {
  71. Flush()
  72. Disable()
  73. CleanUnmatchedRequest()
  74. }
  75. // EnableNetworking enables real HTTP networking
  76. func EnableNetworking() {
  77. mutex.Lock()
  78. defer mutex.Unlock()
  79. config.Networking = true
  80. }
  81. // DisableNetworking disables real HTTP networking
  82. func DisableNetworking() {
  83. mutex.Lock()
  84. defer mutex.Unlock()
  85. config.Networking = false
  86. }
  87. // NetworkingFilter determines if an http.Request should be triggered or not.
  88. func NetworkingFilter(fn FilterRequestFunc) {
  89. mutex.Lock()
  90. defer mutex.Unlock()
  91. config.NetworkingFilters = append(config.NetworkingFilters, fn)
  92. }
  93. // DisableNetworkingFilters disables registered networking filters.
  94. func DisableNetworkingFilters() {
  95. mutex.Lock()
  96. defer mutex.Unlock()
  97. config.NetworkingFilters = []FilterRequestFunc{}
  98. }
  99. // GetUnmatchedRequests returns all requests that have been received but haven't matched any mock
  100. func GetUnmatchedRequests() []*http.Request {
  101. mutex.Lock()
  102. defer mutex.Unlock()
  103. return unmatchedRequests
  104. }
  105. // HasUnmatchedRequest returns true if gock has received any requests that didn't match a mock
  106. func HasUnmatchedRequest() bool {
  107. return len(GetUnmatchedRequests()) > 0
  108. }
  109. // CleanUnmatchedRequest cleans the unmatched requests internal registry.
  110. func CleanUnmatchedRequest() {
  111. mutex.Lock()
  112. defer mutex.Unlock()
  113. unmatchedRequests = []*http.Request{}
  114. }
  115. func trackUnmatchedRequest(req *http.Request) {
  116. mutex.Lock()
  117. defer mutex.Unlock()
  118. unmatchedRequests = append(unmatchedRequests, req)
  119. }
  120. func normalizeURI(uri string) string {
  121. if ok, _ := regexp.MatchString("^http[s]?", uri); !ok {
  122. return "http://" + uri
  123. }
  124. return uri
  125. }