123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- package gock
- import (
- "io"
- "io/ioutil"
- "net/http"
- "net/url"
- "strings"
- )
- // MapRequestFunc represents the required function interface for request mappers.
- type MapRequestFunc func(*http.Request) *http.Request
- // FilterRequestFunc represents the required function interface for request filters.
- type FilterRequestFunc func(*http.Request) bool
- // Request represents the high-level HTTP request used to store
- // request fields used to match intercepted requests.
- type Request struct {
- // Mock stores the parent mock reference for the current request mock used for method delegation.
- Mock Mock
- // Response stores the current Response instance for the current matches Request.
- Response *Response
- // Error stores the latest mock request configuration error.
- Error error
- // Counter stores the pending times that the current mock should be active.
- Counter int
- // Persisted stores if the current mock should be always active.
- Persisted bool
- // URLStruct stores the parsed URL as *url.URL struct.
- URLStruct *url.URL
- // Method stores the Request HTTP method to match.
- Method string
- // CompressionScheme stores the Request Compression scheme to match and use for decompression.
- CompressionScheme string
- // Header stores the HTTP header fields to match.
- Header http.Header
- // Cookies stores the Request HTTP cookies values to match.
- Cookies []*http.Cookie
- // BodyBuffer stores the body data to match.
- BodyBuffer []byte
- // Mappers stores the request functions mappers used for matching.
- Mappers []MapRequestFunc
- // Filters stores the request functions filters used for matching.
- Filters []FilterRequestFunc
- }
- // NewRequest creates a new Request instance.
- func NewRequest() *Request {
- return &Request{
- Counter: 1,
- URLStruct: &url.URL{},
- Header: make(http.Header),
- }
- }
- // URL defines the mock URL to match.
- func (r *Request) URL(uri string) *Request {
- r.URLStruct, r.Error = url.Parse(uri)
- return r
- }
- // SetURL defines the url.URL struct to be used for matching.
- func (r *Request) SetURL(u *url.URL) *Request {
- r.URLStruct = u
- return r
- }
- // Path defines the mock URL path value to match.
- func (r *Request) Path(path string) *Request {
- r.URLStruct.Path = path
- return r
- }
- // Get specifies the GET method and the given URL path to match.
- func (r *Request) Get(path string) *Request {
- return r.method("GET", path)
- }
- // Post specifies the POST method and the given URL path to match.
- func (r *Request) Post(path string) *Request {
- return r.method("POST", path)
- }
- // Put specifies the PUT method and the given URL path to match.
- func (r *Request) Put(path string) *Request {
- return r.method("PUT", path)
- }
- // Delete specifies the DELETE method and the given URL path to match.
- func (r *Request) Delete(path string) *Request {
- return r.method("DELETE", path)
- }
- // Patch specifies the PATCH method and the given URL path to match.
- func (r *Request) Patch(path string) *Request {
- return r.method("PATCH", path)
- }
- // Head specifies the HEAD method and the given URL path to match.
- func (r *Request) Head(path string) *Request {
- return r.method("HEAD", path)
- }
- // method is a DRY shortcut used to declare the expected HTTP method and URL path.
- func (r *Request) method(method, path string) *Request {
- if path != "/" {
- r.URLStruct.Path = path
- }
- r.Method = strings.ToUpper(method)
- return r
- }
- // Body defines the body data to match based on a io.Reader interface.
- func (r *Request) Body(body io.Reader) *Request {
- r.BodyBuffer, r.Error = ioutil.ReadAll(body)
- return r
- }
- // BodyString defines the body to match based on a given string.
- func (r *Request) BodyString(body string) *Request {
- r.BodyBuffer = []byte(body)
- return r
- }
- // File defines the body to match based on the given file path string.
- func (r *Request) File(path string) *Request {
- r.BodyBuffer, r.Error = ioutil.ReadFile(path)
- return r
- }
- // Compression defines the request compression scheme, and enables automatic body decompression.
- // Supports only the "gzip" scheme so far.
- func (r *Request) Compression(scheme string) *Request {
- r.Header.Set("Content-Encoding", scheme)
- r.CompressionScheme = scheme
- return r
- }
- // JSON defines the JSON body to match based on a given structure.
- func (r *Request) JSON(data interface{}) *Request {
- if r.Header.Get("Content-Type") == "" {
- r.Header.Set("Content-Type", "application/json")
- }
- r.BodyBuffer, r.Error = readAndDecode(data, "json")
- return r
- }
- // XML defines the XML body to match based on a given structure.
- func (r *Request) XML(data interface{}) *Request {
- if r.Header.Get("Content-Type") == "" {
- r.Header.Set("Content-Type", "application/xml")
- }
- r.BodyBuffer, r.Error = readAndDecode(data, "xml")
- return r
- }
- // MatchType defines the request Content-Type MIME header field.
- // Supports type alias. E.g: json, xml, form, text...
- func (r *Request) MatchType(kind string) *Request {
- mime := BodyTypeAliases[kind]
- if mime != "" {
- kind = mime
- }
- r.Header.Set("Content-Type", kind)
- return r
- }
- // MatchHeader defines a new key and value header to match.
- func (r *Request) MatchHeader(key, value string) *Request {
- r.Header.Set(key, value)
- return r
- }
- // HeaderPresent defines that a header field must be present in the request.
- func (r *Request) HeaderPresent(key string) *Request {
- r.Header.Set(key, ".*")
- return r
- }
- // MatchHeaders defines a map of key-value headers to match.
- func (r *Request) MatchHeaders(headers map[string]string) *Request {
- for key, value := range headers {
- r.Header.Set(key, value)
- }
- return r
- }
- // MatchParam defines a new key and value URL query param to match.
- func (r *Request) MatchParam(key, value string) *Request {
- query := r.URLStruct.Query()
- query.Set(key, value)
- r.URLStruct.RawQuery = query.Encode()
- return r
- }
- // MatchParams defines a map of URL query param key-value to match.
- func (r *Request) MatchParams(params map[string]string) *Request {
- query := r.URLStruct.Query()
- for key, value := range params {
- query.Set(key, value)
- }
- r.URLStruct.RawQuery = query.Encode()
- return r
- }
- // ParamPresent matches if the given query param key is present in the URL.
- func (r *Request) ParamPresent(key string) *Request {
- r.MatchParam(key, ".*")
- return r
- }
- // Persist defines the current HTTP mock as persistent and won't be removed after intercepting it.
- func (r *Request) Persist() *Request {
- r.Persisted = true
- return r
- }
- // Times defines the number of times that the current HTTP mock should remain active.
- func (r *Request) Times(num int) *Request {
- r.Counter = num
- return r
- }
- // AddMatcher adds a new matcher function to match the request.
- func (r *Request) AddMatcher(fn MatchFunc) *Request {
- r.Mock.AddMatcher(fn)
- return r
- }
- // SetMatcher sets a new matcher function to match the request.
- func (r *Request) SetMatcher(matcher Matcher) *Request {
- r.Mock.SetMatcher(matcher)
- return r
- }
- // Map adds a new request mapper function to map http.Request before the matching process.
- func (r *Request) Map(fn MapRequestFunc) *Request {
- r.Mappers = append(r.Mappers, fn)
- return r
- }
- // Filter filters a new request filter function to filter http.Request before the matching process.
- func (r *Request) Filter(fn FilterRequestFunc) *Request {
- r.Filters = append(r.Filters, fn)
- return r
- }
- // EnableNetworking enables the use real networking for the current mock.
- func (r *Request) EnableNetworking() *Request {
- if r.Response != nil {
- r.Response.UseNetwork = true
- }
- return r
- }
- // Reply defines the Response status code and returns the mock Response DSL.
- func (r *Request) Reply(status int) *Response {
- return r.Response.Status(status)
- }
- // ReplyError defines the Response simulated error.
- func (r *Request) ReplyError(err error) *Response {
- return r.Response.SetError(err)
- }
- // ReplyFunc allows the developer to define the mock response via a custom function.
- func (r *Request) ReplyFunc(replier func(*Response)) *Response {
- replier(r.Response)
- return r.Response
- }
|