response.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. package gock
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "encoding/xml"
  6. "io"
  7. "io/ioutil"
  8. "net/http"
  9. "time"
  10. )
  11. // MapResponseFunc represents the required function interface impletemed by response mappers.
  12. type MapResponseFunc func(*http.Response) *http.Response
  13. // FilterResponseFunc represents the required function interface impletemed by response filters.
  14. type FilterResponseFunc func(*http.Response) bool
  15. // Response represents high-level HTTP fields to configure
  16. // and define HTTP responses intercepted by gock.
  17. type Response struct {
  18. // Mock stores the parent mock reference for the current response mock used for method delegation.
  19. Mock Mock
  20. // Error stores the latest response configuration or injected error.
  21. Error error
  22. // UseNetwork enables the use of real network for the current mock.
  23. UseNetwork bool
  24. // StatusCode stores the response status code.
  25. StatusCode int
  26. // Headers stores the response headers.
  27. Header http.Header
  28. // Cookies stores the response cookie fields.
  29. Cookies []*http.Cookie
  30. // BodyBuffer stores the array of bytes to use as body.
  31. BodyBuffer []byte
  32. // ResponseDelay stores the simulated response delay.
  33. ResponseDelay time.Duration
  34. // Mappers stores the request functions mappers used for matching.
  35. Mappers []MapResponseFunc
  36. // Filters stores the request functions filters used for matching.
  37. Filters []FilterResponseFunc
  38. }
  39. // NewResponse creates a new Response.
  40. func NewResponse() *Response {
  41. return &Response{Header: make(http.Header)}
  42. }
  43. // Status defines the desired HTTP status code to reply in the current response.
  44. func (r *Response) Status(code int) *Response {
  45. r.StatusCode = code
  46. return r
  47. }
  48. // Type defines the response Content-Type MIME header field.
  49. // Supports type alias. E.g: json, xml, form, text...
  50. func (r *Response) Type(kind string) *Response {
  51. mime := BodyTypeAliases[kind]
  52. if mime != "" {
  53. kind = mime
  54. }
  55. r.Header.Set("Content-Type", kind)
  56. return r
  57. }
  58. // SetHeader sets a new header field in the mock response.
  59. func (r *Response) SetHeader(key, value string) *Response {
  60. r.Header.Set(key, value)
  61. return r
  62. }
  63. // AddHeader adds a new header field in the mock response
  64. // with out removing an existent one.
  65. func (r *Response) AddHeader(key, value string) *Response {
  66. r.Header.Add(key, value)
  67. return r
  68. }
  69. // SetHeaders sets a map of header fields in the mock response.
  70. func (r *Response) SetHeaders(headers map[string]string) *Response {
  71. for key, value := range headers {
  72. r.Header.Add(key, value)
  73. }
  74. return r
  75. }
  76. // Body sets the HTTP response body to be used.
  77. func (r *Response) Body(body io.Reader) *Response {
  78. r.BodyBuffer, r.Error = ioutil.ReadAll(body)
  79. return r
  80. }
  81. // BodyString defines the response body as string.
  82. func (r *Response) BodyString(body string) *Response {
  83. r.BodyBuffer = []byte(body)
  84. return r
  85. }
  86. // File defines the response body reading the data
  87. // from disk based on the file path string.
  88. func (r *Response) File(path string) *Response {
  89. r.BodyBuffer, r.Error = ioutil.ReadFile(path)
  90. return r
  91. }
  92. // JSON defines the response body based on a JSON based input.
  93. func (r *Response) JSON(data interface{}) *Response {
  94. r.Header.Set("Content-Type", "application/json")
  95. r.BodyBuffer, r.Error = readAndDecode(data, "json")
  96. return r
  97. }
  98. // XML defines the response body based on a XML based input.
  99. func (r *Response) XML(data interface{}) *Response {
  100. r.Header.Set("Content-Type", "application/xml")
  101. r.BodyBuffer, r.Error = readAndDecode(data, "xml")
  102. return r
  103. }
  104. // SetError defines the response simulated error.
  105. func (r *Response) SetError(err error) *Response {
  106. r.Error = err
  107. return r
  108. }
  109. // Delay defines the response simulated delay.
  110. // This feature is still experimental and will be improved in the future.
  111. func (r *Response) Delay(delay time.Duration) *Response {
  112. r.ResponseDelay = delay
  113. return r
  114. }
  115. // Map adds a new response mapper function to map http.Response before the matching process.
  116. func (r *Response) Map(fn MapResponseFunc) *Response {
  117. r.Mappers = append(r.Mappers, fn)
  118. return r
  119. }
  120. // Filter filters a new request filter function to filter http.Request before the matching process.
  121. func (r *Response) Filter(fn FilterResponseFunc) *Response {
  122. r.Filters = append(r.Filters, fn)
  123. return r
  124. }
  125. // EnableNetworking enables the use real networking for the current mock.
  126. func (r *Response) EnableNetworking() *Response {
  127. r.UseNetwork = true
  128. return r
  129. }
  130. // Done returns true if the mock was done and disabled.
  131. func (r *Response) Done() bool {
  132. return r.Mock.Done()
  133. }
  134. func readAndDecode(data interface{}, kind string) ([]byte, error) {
  135. buf := &bytes.Buffer{}
  136. switch data.(type) {
  137. case string:
  138. buf.WriteString(data.(string))
  139. case []byte:
  140. buf.Write(data.([]byte))
  141. default:
  142. var err error
  143. if kind == "xml" {
  144. err = xml.NewEncoder(buf).Encode(data)
  145. } else {
  146. err = json.NewEncoder(buf).Encode(data)
  147. }
  148. if err != nil {
  149. return nil, err
  150. }
  151. }
  152. return ioutil.ReadAll(buf)
  153. }