request.go 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535
  1. package httpexpect
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "io/ioutil"
  10. "mime/multipart"
  11. "net"
  12. "net/http"
  13. "net/url"
  14. "os"
  15. "reflect"
  16. "sort"
  17. "strings"
  18. "sync"
  19. "time"
  20. "github.com/ajg/form"
  21. "github.com/fatih/structs"
  22. "github.com/google/go-querystring/query"
  23. "github.com/gorilla/websocket"
  24. "github.com/imkira/go-interpol"
  25. )
  26. // Request provides methods to incrementally build http.Request object,
  27. // send it, and receive response.
  28. type Request struct {
  29. mu sync.Mutex
  30. config Config
  31. chain *chain
  32. redirectPolicy RedirectPolicy
  33. maxRedirects int
  34. retryPolicy RetryPolicy
  35. maxRetries int
  36. minRetryDelay time.Duration
  37. maxRetryDelay time.Duration
  38. sleepFn func(d time.Duration) <-chan time.Time
  39. timeout time.Duration
  40. httpReq *http.Request
  41. path string
  42. query url.Values
  43. form url.Values
  44. formbuf *bytes.Buffer
  45. multipart *multipart.Writer
  46. multipartFn func(w io.Writer) *multipart.Writer
  47. bodySetter string
  48. typeSetter string
  49. forceType bool
  50. expectCalled bool
  51. wsUpgrade bool
  52. transformers []func(*http.Request)
  53. matchers []func(*Response)
  54. }
  55. // Deprecated: use NewRequestC instead.
  56. func NewRequest(config Config, method, path string, pathargs ...interface{}) *Request {
  57. return NewRequestC(config, method, path, pathargs...)
  58. }
  59. // NewRequestC returns a new Request instance.
  60. //
  61. // Requirements for config are same as for WithConfig function.
  62. //
  63. // method defines the HTTP method (GET, POST, PUT, etc.). path defines url path.
  64. //
  65. // Simple interpolation is allowed for {named} parameters in path:
  66. // - if pathargs is given, it's used to substitute first len(pathargs) parameters,
  67. // regardless of their names
  68. // - if WithPath() or WithPathObject() is called, it's used to substitute given
  69. // parameters by name
  70. //
  71. // For example:
  72. //
  73. // req := NewRequestC(config, "POST", "/repos/{user}/{repo}", "iris-contrib", "httpexpect")
  74. // // path will be "/repos/iris-contrib/httpexpect"
  75. //
  76. // Or:
  77. //
  78. // req := NewRequestC(config, "POST", "/repos/{user}/{repo}")
  79. // req.WithPath("user", "iris-contrib")
  80. // req.WithPath("repo", "httpexpect")
  81. // // path will be "/repos/iris-contrib/httpexpect"
  82. //
  83. // After interpolation, path is urlencoded and appended to Config.BaseURL,
  84. // separated by slash. If BaseURL ends with a slash and path (after interpolation)
  85. // starts with a slash, only single slash is inserted.
  86. func NewRequestC(config Config, method, path string, pathargs ...interface{}) *Request {
  87. config = config.withDefaults()
  88. return newRequest(
  89. newChainWithConfig(fmt.Sprintf("Request(%q)", method), config),
  90. config,
  91. method,
  92. path,
  93. pathargs...,
  94. )
  95. }
  96. func newRequest(
  97. parent *chain, config Config, method, path string, pathargs ...interface{},
  98. ) *Request {
  99. config.validate()
  100. r := &Request{
  101. config: config,
  102. chain: parent.clone(),
  103. redirectPolicy: defaultRedirectPolicy,
  104. maxRedirects: -1,
  105. retryPolicy: RetryTimeoutAndServerErrors,
  106. maxRetries: 0,
  107. minRetryDelay: time.Millisecond * 50,
  108. maxRetryDelay: time.Second * 5,
  109. sleepFn: func(d time.Duration) <-chan time.Time {
  110. return time.After(d)
  111. },
  112. multipartFn: func(w io.Writer) *multipart.Writer {
  113. return multipart.NewWriter(w)
  114. },
  115. }
  116. opChain := r.chain.enter("")
  117. defer opChain.leave()
  118. r.initPath(opChain, path, pathargs...)
  119. r.initReq(opChain, method)
  120. r.chain.setRequest(r)
  121. return r
  122. }
  123. func (r *Request) initPath(opChain *chain, path string, pathargs ...interface{}) {
  124. if len(pathargs) != 0 {
  125. var n int
  126. var err error
  127. path, err = interpol.WithFunc(path, func(k string, w io.Writer) error {
  128. if n < len(pathargs) {
  129. if pathargs[n] == nil {
  130. opChain.fail(AssertionFailure{
  131. Type: AssertValid,
  132. Actual: &AssertionValue{pathargs},
  133. Errors: []error{
  134. fmt.Errorf("unexpected nil argument at index %d", n),
  135. },
  136. })
  137. } else {
  138. mustWrite(w, fmt.Sprint(pathargs[n]))
  139. }
  140. } else {
  141. mustWrite(w, "{")
  142. mustWrite(w, k)
  143. mustWrite(w, "}")
  144. }
  145. n++
  146. return nil
  147. })
  148. if err != nil {
  149. opChain.fail(AssertionFailure{
  150. Type: AssertValid,
  151. Actual: &AssertionValue{path},
  152. Errors: []error{
  153. errors.New("invalid interpol string"),
  154. err,
  155. },
  156. })
  157. }
  158. }
  159. r.path = path
  160. }
  161. func (r *Request) initReq(opChain *chain, method string) {
  162. httpReq, err := r.config.RequestFactory.NewRequest(method, r.config.BaseURL, nil)
  163. if err != nil {
  164. opChain.fail(AssertionFailure{
  165. Type: AssertOperation,
  166. Errors: []error{
  167. errors.New("failed to create http request"),
  168. err,
  169. },
  170. })
  171. }
  172. r.httpReq = httpReq
  173. }
  174. // Alias is similar to Value.Alias.
  175. func (r *Request) Alias(name string) *Request {
  176. opChain := r.chain.enter("Alias(%q)", name)
  177. defer opChain.leave()
  178. r.mu.Lock()
  179. defer r.mu.Unlock()
  180. r.chain.setAlias(name)
  181. return r
  182. }
  183. // WithName sets convenient request name.
  184. // This name will be included in assertion reports for this request.
  185. // It does not affect assertion chain path, inlike Alias.
  186. //
  187. // Example:
  188. //
  189. // req := NewRequestC(config, "POST", "/api/login")
  190. // req.WithName("Login Request")
  191. func (r *Request) WithName(name string) *Request {
  192. opChain := r.chain.enter("WithName()")
  193. defer opChain.leave()
  194. r.mu.Lock()
  195. defer r.mu.Unlock()
  196. if opChain.failed() {
  197. return r
  198. }
  199. if !r.checkOrder(opChain, "WithName()") {
  200. return r
  201. }
  202. r.chain.setRequestName(name)
  203. return r
  204. }
  205. // WithReporter sets reporter to be used for this request.
  206. //
  207. // The new reporter overwrites AssertionHandler.
  208. // The new AssertionHandler is DefaultAssertionHandler with specified reporter,
  209. // existing Config.Formatter and nil Logger.
  210. // It will be used to report formatted fatal failure messages.
  211. //
  212. // Example:
  213. //
  214. // req := NewRequestC(config, "GET", "http://example.com/path")
  215. // req.WithReporter(t)
  216. func (r *Request) WithReporter(reporter Reporter) *Request {
  217. opChain := r.chain.enter("WithReporter()")
  218. defer opChain.leave()
  219. r.mu.Lock()
  220. defer r.mu.Unlock()
  221. if opChain.failed() {
  222. return r
  223. }
  224. if !r.checkOrder(opChain, "WithReporter()") {
  225. return r
  226. }
  227. if reporter == nil {
  228. opChain.fail(AssertionFailure{
  229. Type: AssertUsage,
  230. Errors: []error{
  231. errors.New("unexpected nil argument"),
  232. },
  233. })
  234. return r
  235. }
  236. handler := &DefaultAssertionHandler{
  237. Reporter: reporter,
  238. Formatter: r.config.Formatter,
  239. }
  240. r.chain.setHandler(handler)
  241. return r
  242. }
  243. // WithAssertionHandler sets assertion handler to be used for this request.
  244. //
  245. // The new handler overwrites assertion handler that will be used
  246. // by Request and its children (Response, Body, etc.).
  247. // It will be used to format and report test Failure or Success.
  248. //
  249. // Example:
  250. //
  251. // req := NewRequestC(config, "GET", "http://example.com/path")
  252. // req.WithAssertionHandler(&DefaultAssertionHandler{
  253. // Reporter: reporter,
  254. // Formatter: formatter,
  255. // })
  256. func (r *Request) WithAssertionHandler(handler AssertionHandler) *Request {
  257. opChain := r.chain.enter("WithAssertionHandler()")
  258. defer opChain.leave()
  259. r.mu.Lock()
  260. defer r.mu.Unlock()
  261. if opChain.failed() {
  262. return r
  263. }
  264. if !r.checkOrder(opChain, "WithAssertionHandler()") {
  265. return r
  266. }
  267. if handler == nil {
  268. opChain.fail(AssertionFailure{
  269. Type: AssertUsage,
  270. Errors: []error{
  271. errors.New("unexpected nil argument"),
  272. },
  273. })
  274. return r
  275. }
  276. r.chain.setHandler(handler)
  277. return r
  278. }
  279. // WithMatcher attaches a matcher to the request.
  280. // All attached matchers are invoked in the Expect method for a newly
  281. // created Response.
  282. //
  283. // Example:
  284. //
  285. // req := NewRequestC(config, "GET", "/path")
  286. // req.WithMatcher(func (resp *httpexpect.Response) {
  287. // resp.Header("API-Version").NotEmpty()
  288. // })
  289. func (r *Request) WithMatcher(matcher func(*Response)) *Request {
  290. opChain := r.chain.enter("WithMatcher()")
  291. defer opChain.leave()
  292. r.mu.Lock()
  293. defer r.mu.Unlock()
  294. if opChain.failed() {
  295. return r
  296. }
  297. if !r.checkOrder(opChain, "WithMatcher()") {
  298. return r
  299. }
  300. if matcher == nil {
  301. opChain.fail(AssertionFailure{
  302. Type: AssertUsage,
  303. Errors: []error{
  304. errors.New("unexpected nil argument"),
  305. },
  306. })
  307. return r
  308. }
  309. r.matchers = append(r.matchers, matcher)
  310. return r
  311. }
  312. // WithTransformer attaches a transform to the Request.
  313. // All attachhed transforms are invoked in the Expect methods for
  314. // http.Request struct, after it's encoded and before it's sent.
  315. //
  316. // Example:
  317. //
  318. // req := NewRequestC(config, "PUT", "http://example.com/path")
  319. // req.WithTransformer(func(r *http.Request) { r.Header.Add("foo", "bar") })
  320. func (r *Request) WithTransformer(transformer func(*http.Request)) *Request {
  321. opChain := r.chain.enter("WithTransformer()")
  322. defer opChain.leave()
  323. r.mu.Lock()
  324. defer r.mu.Unlock()
  325. if opChain.failed() {
  326. return r
  327. }
  328. if !r.checkOrder(opChain, "WithTransformer()") {
  329. return r
  330. }
  331. if transformer == nil {
  332. opChain.fail(AssertionFailure{
  333. Type: AssertUsage,
  334. Errors: []error{
  335. errors.New("unexpected nil argument"),
  336. },
  337. })
  338. return r
  339. }
  340. r.transformers = append(r.transformers, transformer)
  341. return r
  342. }
  343. // WithClient sets client.
  344. //
  345. // The new client overwrites Config.Client. It will be used once to send the
  346. // request and receive a response.
  347. //
  348. // Example:
  349. //
  350. // req := NewRequestC(config, "GET", "/path")
  351. // req.WithClient(&http.Client{
  352. // Transport: &http.Transport{
  353. // DisableCompression: true,
  354. // },
  355. // })
  356. func (r *Request) WithClient(client Client) *Request {
  357. opChain := r.chain.enter("WithClient()")
  358. defer opChain.leave()
  359. r.mu.Lock()
  360. defer r.mu.Unlock()
  361. if opChain.failed() {
  362. return r
  363. }
  364. if !r.checkOrder(opChain, "WithClient()") {
  365. return r
  366. }
  367. if client == nil {
  368. opChain.fail(AssertionFailure{
  369. Type: AssertUsage,
  370. Errors: []error{
  371. errors.New("unexpected nil argument"),
  372. },
  373. })
  374. return r
  375. }
  376. r.config.Client = client
  377. return r
  378. }
  379. // WithHandler configures client to invoke the given handler directly.
  380. //
  381. // If Config.Client is http.Client, then only its Transport field is overwritten
  382. // because the client may contain some state shared among requests like a cookie
  383. // jar. Otherwise, the whole client is overwritten with a new client.
  384. //
  385. // Example:
  386. //
  387. // req := NewRequestC(config, "GET", "/path")
  388. // req.WithHandler(myServer.someHandler)
  389. func (r *Request) WithHandler(handler http.Handler) *Request {
  390. opChain := r.chain.enter("WithHandler()")
  391. defer opChain.leave()
  392. r.mu.Lock()
  393. defer r.mu.Unlock()
  394. if opChain.failed() {
  395. return r
  396. }
  397. if !r.checkOrder(opChain, "WithHandler()") {
  398. return r
  399. }
  400. if handler == nil {
  401. opChain.fail(AssertionFailure{
  402. Type: AssertUsage,
  403. Errors: []error{
  404. errors.New("unexpected nil argument"),
  405. },
  406. })
  407. return r
  408. }
  409. if client, ok := r.config.Client.(*http.Client); ok {
  410. clientCopy := *client
  411. clientCopy.Transport = NewBinder(handler)
  412. r.config.Client = &clientCopy
  413. } else {
  414. r.config.Client = &http.Client{
  415. Transport: NewBinder(handler),
  416. Jar: NewCookieJar(),
  417. }
  418. }
  419. return r
  420. }
  421. // WithContext sets the context.
  422. //
  423. // Config.Context will be overwritten.
  424. //
  425. // Any retries will stop after one is cancelled.
  426. // If the intended behavior is to continue any further retries, use WithTimeout.
  427. //
  428. // Example:
  429. //
  430. // ctx, _ = context.WithTimeout(context.Background(), time.Duration(3)*time.Second)
  431. // req := NewRequestC(config, "GET", "/path")
  432. // req.WithContext(ctx)
  433. // req.Expect().Status(http.StatusOK)
  434. func (r *Request) WithContext(ctx context.Context) *Request {
  435. opChain := r.chain.enter("WithContext()")
  436. defer opChain.leave()
  437. r.mu.Lock()
  438. defer r.mu.Unlock()
  439. if opChain.failed() {
  440. return r
  441. }
  442. if !r.checkOrder(opChain, "WithContext()") {
  443. return r
  444. }
  445. if ctx == nil {
  446. opChain.fail(AssertionFailure{
  447. Type: AssertUsage,
  448. Errors: []error{
  449. errors.New("unexpected nil argument"),
  450. },
  451. })
  452. return r
  453. }
  454. r.config.Context = ctx
  455. return r
  456. }
  457. // WithTimeout sets a timeout duration for the request.
  458. //
  459. // Will attach to the request a context.WithTimeout around the Config.Context
  460. // or any context set WithContext. If these are nil, the new context will be
  461. // created on top of a context.Background().
  462. //
  463. // Any retries will continue after one is cancelled.
  464. // If the intended behavior is to stop any further retries, use WithContext or
  465. // Config.Context.
  466. //
  467. // Example:
  468. //
  469. // req := NewRequestC(config, "GET", "/path")
  470. // req.WithTimeout(time.Duration(3)*time.Second)
  471. // req.Expect().Status(http.StatusOK)
  472. func (r *Request) WithTimeout(timeout time.Duration) *Request {
  473. opChain := r.chain.enter("WithTimeout()")
  474. defer opChain.leave()
  475. r.mu.Lock()
  476. defer r.mu.Unlock()
  477. if opChain.failed() {
  478. return r
  479. }
  480. if !r.checkOrder(opChain, "WithTimeout()") {
  481. return r
  482. }
  483. r.timeout = timeout
  484. return r
  485. }
  486. // RedirectPolicy defines how redirection responses are handled.
  487. //
  488. // Status codes 307, 308 require resending body. They are followed only if
  489. // redirect policy is FollowAllRedirects.
  490. //
  491. // Status codes 301, 302, 303 don't require resending body. On such redirect,
  492. // http.Client automatically switches HTTP method to GET, if it's not GET or
  493. // HEAD already. These redirects are followed if redirect policy is either
  494. // FollowAllRedirects or FollowRedirectsWithoutBody.
  495. //
  496. // Default redirect policy is FollowRedirectsWithoutBody.
  497. type RedirectPolicy int
  498. const (
  499. // indicates that WithRedirectPolicy was not called
  500. defaultRedirectPolicy RedirectPolicy = iota
  501. // DontFollowRedirects forbids following any redirects.
  502. // Redirection response is returned to the user and can be inspected.
  503. DontFollowRedirects
  504. // FollowAllRedirects allows following any redirects, including those
  505. // which require resending body.
  506. FollowAllRedirects
  507. // FollowRedirectsWithoutBody allows following only redirects which
  508. // don't require resending body.
  509. // If redirect requires resending body, it's not followed, and redirection
  510. // response is returned instead.
  511. FollowRedirectsWithoutBody
  512. )
  513. // WithRedirectPolicy sets policy for redirection response handling.
  514. //
  515. // How redirect is handled depends on both response status code and
  516. // redirect policy. See comments for RedirectPolicy for details.
  517. //
  518. // Default redirect policy is defined by Client implementation.
  519. // Default behavior of http.Client corresponds to FollowRedirectsWithoutBody.
  520. //
  521. // This method can be used only if Client interface points to
  522. // *http.Client struct, since we rely on it in redirect handling.
  523. //
  524. // Example:
  525. //
  526. // req1 := NewRequestC(config, "POST", "/path")
  527. // req1.WithRedirectPolicy(FollowAllRedirects)
  528. // req1.Expect().Status(http.StatusOK)
  529. //
  530. // req2 := NewRequestC(config, "POST", "/path")
  531. // req2.WithRedirectPolicy(DontFollowRedirects)
  532. // req2.Expect().Status(http.StatusPermanentRedirect)
  533. func (r *Request) WithRedirectPolicy(policy RedirectPolicy) *Request {
  534. opChain := r.chain.enter("WithRedirectPolicy()")
  535. defer opChain.leave()
  536. r.mu.Lock()
  537. defer r.mu.Unlock()
  538. if opChain.failed() {
  539. return r
  540. }
  541. if !r.checkOrder(opChain, "WithRedirectPolicy()") {
  542. return r
  543. }
  544. r.redirectPolicy = policy
  545. return r
  546. }
  547. // WithMaxRedirects sets maximum number of redirects to follow.
  548. //
  549. // If the number of redirects exceedes this limit, request is failed.
  550. //
  551. // Default limit is defined by Client implementation.
  552. // Default behavior of http.Client corresponds to maximum of 10-1 redirects.
  553. //
  554. // This method can be used only if Client interface points to
  555. // *http.Client struct, since we rely on it in redirect handling.
  556. //
  557. // Example:
  558. //
  559. // req1 := NewRequestC(config, "POST", "/path")
  560. // req1.WithMaxRedirects(1)
  561. // req1.Expect().Status(http.StatusOK)
  562. func (r *Request) WithMaxRedirects(maxRedirects int) *Request {
  563. opChain := r.chain.enter("WithMaxRedirects()")
  564. defer opChain.leave()
  565. r.mu.Lock()
  566. defer r.mu.Unlock()
  567. if opChain.failed() {
  568. return r
  569. }
  570. if !r.checkOrder(opChain, "WithMaxRedirects()") {
  571. return r
  572. }
  573. if maxRedirects < 0 {
  574. opChain.fail(AssertionFailure{
  575. Type: AssertValid,
  576. Actual: &AssertionValue{maxRedirects},
  577. Errors: []error{
  578. errors.New("invalid negative argument"),
  579. },
  580. })
  581. return r
  582. }
  583. r.maxRedirects = maxRedirects
  584. return r
  585. }
  586. // RetryPolicy defines how failed requests are retried.
  587. //
  588. // Whether a request is retried depends on error type (if any), response
  589. // status code (if any), and retry policy.
  590. type RetryPolicy int
  591. const (
  592. // DontRetry disables retrying at all.
  593. DontRetry RetryPolicy = iota
  594. // Deprecated: use RetryTimeoutErrors instead.
  595. RetryTemporaryNetworkErrors
  596. // Deprecated: use RetryTimeoutAndServerErrors instead.
  597. RetryTemporaryNetworkAndServerErrors
  598. // RetryTimeoutErrors enables retrying of timeout errors.
  599. // Retry happens if Client returns net.Error and its Timeout() method
  600. // returns true.
  601. RetryTimeoutErrors
  602. // RetryTimeoutAndServerErrors enables retrying of network timeout errors,
  603. // as well as 5xx status codes.
  604. RetryTimeoutAndServerErrors
  605. // RetryAllErrors enables retrying of any error or 4xx/5xx status code.
  606. RetryAllErrors
  607. )
  608. // WithRetryPolicy sets policy for retries.
  609. //
  610. // Whether a request is retried depends on error type (if any), response
  611. // status code (if any), and retry policy.
  612. //
  613. // How much retry attempts happens is defined by WithMaxRetries().
  614. // How much to wait between attempts is defined by WithRetryDelay().
  615. //
  616. // Default retry policy is RetryTimeoutAndServerErrors, but
  617. // default maximum number of retries is zero, so no retries happen
  618. // unless WithMaxRetries() is called.
  619. //
  620. // Example:
  621. //
  622. // req := NewRequestC(config, "POST", "/path")
  623. // req.WithRetryPolicy(RetryAllErrors)
  624. // req.Expect().Status(http.StatusOK)
  625. func (r *Request) WithRetryPolicy(policy RetryPolicy) *Request {
  626. opChain := r.chain.enter("WithRetryPolicy()")
  627. defer opChain.leave()
  628. r.mu.Lock()
  629. defer r.mu.Unlock()
  630. if opChain.failed() {
  631. return r
  632. }
  633. if !r.checkOrder(opChain, "WithRetryPolicy()") {
  634. return r
  635. }
  636. r.retryPolicy = policy
  637. return r
  638. }
  639. // WithMaxRetries sets maximum number of retry attempts.
  640. //
  641. // After first request failure, additional retry attempts may happen,
  642. // depending on the retry policy.
  643. //
  644. // Setting this to zero disables retries, i.e. only one request is sent.
  645. // Setting this to N enables retries, and up to N+1 requests may be sent.
  646. //
  647. // Default number of retries is zero, i.e. retries are disabled.
  648. //
  649. // Example:
  650. //
  651. // req := NewRequestC(config, "POST", "/path")
  652. // req.WithMaxRetries(1)
  653. // req.Expect().Status(http.StatusOK)
  654. func (r *Request) WithMaxRetries(maxRetries int) *Request {
  655. opChain := r.chain.enter("WithMaxRetries()")
  656. defer opChain.leave()
  657. r.mu.Lock()
  658. defer r.mu.Unlock()
  659. if opChain.failed() {
  660. return r
  661. }
  662. if !r.checkOrder(opChain, "WithMaxRetries()") {
  663. return r
  664. }
  665. if maxRetries < 0 {
  666. opChain.fail(AssertionFailure{
  667. Type: AssertValid,
  668. Actual: &AssertionValue{maxRetries},
  669. Errors: []error{
  670. errors.New("invalid negative argument"),
  671. },
  672. })
  673. return r
  674. }
  675. r.maxRetries = maxRetries
  676. return r
  677. }
  678. // WithRetryDelay sets minimum and maximum delay between retries.
  679. //
  680. // If multiple retry attempts happen, delay between attempts starts from
  681. // minDelay and then grows exponentionally until it reaches maxDelay.
  682. //
  683. // Default delay range is [50ms; 5s].
  684. //
  685. // Example:
  686. //
  687. // req := NewRequestC(config, "POST", "/path")
  688. // req.WithRetryDelay(time.Second, time.Minute)
  689. // req.Expect().Status(http.StatusOK)
  690. func (r *Request) WithRetryDelay(minDelay, maxDelay time.Duration) *Request {
  691. opChain := r.chain.enter("WithRetryDelay()")
  692. defer opChain.leave()
  693. r.mu.Lock()
  694. defer r.mu.Unlock()
  695. if opChain.failed() {
  696. return r
  697. }
  698. if !r.checkOrder(opChain, "WithRetryDelay()") {
  699. return r
  700. }
  701. if !(minDelay <= maxDelay) {
  702. opChain.fail(AssertionFailure{
  703. Type: AssertValid,
  704. Actual: &AssertionValue{
  705. [2]time.Duration{minDelay, maxDelay},
  706. },
  707. Errors: []error{
  708. errors.New("invalid delay range"),
  709. },
  710. })
  711. return r
  712. }
  713. r.minRetryDelay = minDelay
  714. r.maxRetryDelay = maxDelay
  715. return r
  716. }
  717. // WithWebsocketUpgrade enables upgrades the connection to websocket.
  718. //
  719. // At least the following fields are added to the request header:
  720. //
  721. // Upgrade: websocket
  722. // Connection: Upgrade
  723. //
  724. // The actual set of header fields is define by the protocol implementation
  725. // in the gorilla/websocket package.
  726. //
  727. // The user should then call the Response.Websocket() method which returns
  728. // the Websocket instance. This instance can be used to send messages to the
  729. // server, to inspect the received messages, and to close the websocket.
  730. //
  731. // Example:
  732. //
  733. // req := NewRequestC(config, "GET", "/path")
  734. // req.WithWebsocketUpgrade()
  735. // ws := req.Expect().Status(http.StatusSwitchingProtocols).Websocket()
  736. // defer ws.Disconnect()
  737. func (r *Request) WithWebsocketUpgrade() *Request {
  738. opChain := r.chain.enter("WithWebsocketUpgrade()")
  739. defer opChain.leave()
  740. r.mu.Lock()
  741. defer r.mu.Unlock()
  742. if opChain.failed() {
  743. return r
  744. }
  745. if !r.checkOrder(opChain, "WithWebsocketUpgrade()") {
  746. return r
  747. }
  748. r.wsUpgrade = true
  749. return r
  750. }
  751. // WithWebsocketDialer sets the custom websocket dialer.
  752. //
  753. // The new dialer overwrites Config.WebsocketDialer. It will be used once to establish
  754. // the WebSocket connection and receive a response of handshake result.
  755. //
  756. // Example:
  757. //
  758. // req := NewRequestC(config, "GET", "/path")
  759. // req.WithWebsocketUpgrade()
  760. // req.WithWebsocketDialer(&websocket.Dialer{
  761. // EnableCompression: false,
  762. // })
  763. // ws := req.Expect().Status(http.StatusSwitchingProtocols).Websocket()
  764. // defer ws.Disconnect()
  765. func (r *Request) WithWebsocketDialer(dialer WebsocketDialer) *Request {
  766. opChain := r.chain.enter("WithWebsocketDialer()")
  767. defer opChain.leave()
  768. r.mu.Lock()
  769. defer r.mu.Unlock()
  770. if opChain.failed() {
  771. return r
  772. }
  773. if !r.checkOrder(opChain, "WithWebsocketDialer()") {
  774. return r
  775. }
  776. if dialer == nil {
  777. opChain.fail(AssertionFailure{
  778. Type: AssertUsage,
  779. Errors: []error{
  780. errors.New("unexpected nil argument"),
  781. },
  782. })
  783. return r
  784. }
  785. r.config.WebsocketDialer = dialer
  786. return r
  787. }
  788. // WithPath substitutes named parameters in url path.
  789. //
  790. // value is converted to string using fmt.Sprint(). If there is no named
  791. // parameter '{key}' in url path, failure is reported.
  792. //
  793. // Named parameters are case-insensitive.
  794. //
  795. // Example:
  796. //
  797. // req := NewRequestC(config, "POST", "/repos/{user}/{repo}")
  798. // req.WithPath("user", "iris-contrib")
  799. // req.WithPath("repo", "httpexpect")
  800. // // path will be "/repos/iris-contrib/httpexpect"
  801. func (r *Request) WithPath(key string, value interface{}) *Request {
  802. opChain := r.chain.enter("WithPath()")
  803. defer opChain.leave()
  804. r.mu.Lock()
  805. defer r.mu.Unlock()
  806. if opChain.failed() {
  807. return r
  808. }
  809. if !r.checkOrder(opChain, "WithPath()") {
  810. return r
  811. }
  812. r.withPath(opChain, key, value)
  813. return r
  814. }
  815. // WithPathObject substitutes multiple named parameters in url path.
  816. //
  817. // object should be map or struct. If object is struct, it's converted
  818. // to map using https://github.com/fatih/structs. Structs may contain
  819. // "path" struct tag, similar to "json" struct tag for json.Marshal().
  820. //
  821. // Each map value is converted to string using fmt.Sprint(). If there
  822. // is no named parameter for some map '{key}' in url path, failure is
  823. // reported.
  824. //
  825. // Named parameters are case-insensitive.
  826. //
  827. // Example:
  828. //
  829. // type MyPath struct {
  830. // Login string `path:"user"`
  831. // Repo string
  832. // }
  833. //
  834. // req := NewRequestC(config, "POST", "/repos/{user}/{repo}")
  835. // req.WithPathObject(MyPath{"iris-contrib", "httpexpect"})
  836. // // path will be "/repos/iris-contrib/httpexpect"
  837. //
  838. // req := NewRequestC(config, "POST", "/repos/{user}/{repo}")
  839. // req.WithPathObject(map[string]string{"user": "iris-contrib", "repo": "httpexpect"})
  840. // // path will be "/repos/iris-contrib/httpexpect"
  841. func (r *Request) WithPathObject(object interface{}) *Request {
  842. opChain := r.chain.enter("WithPathObject()")
  843. defer opChain.leave()
  844. r.mu.Lock()
  845. defer r.mu.Unlock()
  846. if opChain.failed() {
  847. return r
  848. }
  849. if !r.checkOrder(opChain, "WithPathObject()") {
  850. return r
  851. }
  852. if object == nil {
  853. return r
  854. }
  855. var (
  856. m map[string]interface{}
  857. ok bool
  858. )
  859. if reflect.Indirect(reflect.ValueOf(object)).Kind() == reflect.Struct {
  860. s := structs.New(object)
  861. s.TagName = "path"
  862. m = s.Map()
  863. } else {
  864. m, ok = canonMap(opChain, object)
  865. if !ok {
  866. return r
  867. }
  868. }
  869. for key, value := range m {
  870. r.withPath(opChain, key, value)
  871. }
  872. return r
  873. }
  874. func (r *Request) withPath(opChain *chain, key string, value interface{}) {
  875. found := false
  876. path, err := interpol.WithFunc(r.path, func(k string, w io.Writer) error {
  877. if strings.EqualFold(k, key) {
  878. if value == nil {
  879. opChain.fail(AssertionFailure{
  880. Type: AssertUsage,
  881. Errors: []error{
  882. fmt.Errorf("unexpected nil interpol argument %q", k),
  883. },
  884. })
  885. } else {
  886. mustWrite(w, fmt.Sprint(value))
  887. found = true
  888. }
  889. } else {
  890. mustWrite(w, "{")
  891. mustWrite(w, k)
  892. mustWrite(w, "}")
  893. }
  894. return nil
  895. })
  896. if err != nil {
  897. opChain.fail(AssertionFailure{
  898. Type: AssertValid,
  899. Actual: &AssertionValue{path},
  900. Errors: []error{
  901. errors.New("invalid interpol string"),
  902. err,
  903. },
  904. })
  905. return
  906. }
  907. if !found {
  908. opChain.fail(AssertionFailure{
  909. Type: AssertUsage,
  910. Errors: []error{
  911. fmt.Errorf("key %q not found in interpol string", key),
  912. },
  913. })
  914. return
  915. }
  916. r.path = path
  917. }
  918. // WithQuery adds query parameter to request URL.
  919. //
  920. // value is converted to string using fmt.Sprint() and urlencoded.
  921. //
  922. // Example:
  923. //
  924. // req := NewRequestC(config, "PUT", "http://example.com/path")
  925. // req.WithQuery("a", 123)
  926. // req.WithQuery("b", "foo")
  927. // // URL is now http://example.com/path?a=123&b=foo
  928. func (r *Request) WithQuery(key string, value interface{}) *Request {
  929. opChain := r.chain.enter("WithQuery()")
  930. defer opChain.leave()
  931. r.mu.Lock()
  932. defer r.mu.Unlock()
  933. if opChain.failed() {
  934. return r
  935. }
  936. if !r.checkOrder(opChain, "WithQuery()") {
  937. return r
  938. }
  939. if value == nil {
  940. opChain.fail(AssertionFailure{
  941. Type: AssertUsage,
  942. Errors: []error{
  943. errors.New("unexpected nil argument"),
  944. },
  945. })
  946. return r
  947. }
  948. if r.query == nil {
  949. r.query = make(url.Values)
  950. }
  951. r.query.Add(key, fmt.Sprint(value))
  952. return r
  953. }
  954. // WithQueryObject adds multiple query parameters to request URL.
  955. //
  956. // object is converted to query string using github.com/google/go-querystring
  957. // if it's a struct or pointer to struct, or github.com/ajg/form otherwise.
  958. //
  959. // Various object types are supported. Structs may contain "url" struct tag,
  960. // similar to "json" struct tag for json.Marshal().
  961. //
  962. // Example:
  963. //
  964. // type MyURL struct {
  965. // A int `url:"a"`
  966. // B string `url:"b"`
  967. // }
  968. //
  969. // req := NewRequestC(config, "PUT", "http://example.com/path")
  970. // req.WithQueryObject(MyURL{A: 123, B: "foo"})
  971. // // URL is now http://example.com/path?a=123&b=foo
  972. //
  973. // req := NewRequestC(config, "PUT", "http://example.com/path")
  974. // req.WithQueryObject(map[string]interface{}{"a": 123, "b": "foo"})
  975. // // URL is now http://example.com/path?a=123&b=foo
  976. func (r *Request) WithQueryObject(object interface{}) *Request {
  977. opChain := r.chain.enter("WithQueryObject()")
  978. defer opChain.leave()
  979. r.mu.Lock()
  980. defer r.mu.Unlock()
  981. if opChain.failed() {
  982. return r
  983. }
  984. if !r.checkOrder(opChain, "WithQueryObject()") {
  985. return r
  986. }
  987. if object == nil {
  988. return r
  989. }
  990. var (
  991. q url.Values
  992. err error
  993. )
  994. if reflect.Indirect(reflect.ValueOf(object)).Kind() == reflect.Struct {
  995. q, err = query.Values(object)
  996. if err != nil {
  997. opChain.fail(AssertionFailure{
  998. Type: AssertValid,
  999. Actual: &AssertionValue{object},
  1000. Errors: []error{
  1001. errors.New("invalid query object"),
  1002. err,
  1003. },
  1004. })
  1005. return r
  1006. }
  1007. } else {
  1008. q, err = form.EncodeToValues(object)
  1009. if err != nil {
  1010. opChain.fail(AssertionFailure{
  1011. Type: AssertValid,
  1012. Actual: &AssertionValue{object},
  1013. Errors: []error{
  1014. errors.New("invalid query object"),
  1015. err,
  1016. },
  1017. })
  1018. return r
  1019. }
  1020. }
  1021. if r.query == nil {
  1022. r.query = make(url.Values)
  1023. }
  1024. for k, v := range q {
  1025. r.query[k] = append(r.query[k], v...)
  1026. }
  1027. return r
  1028. }
  1029. // WithQueryString parses given query string and adds it to request URL.
  1030. //
  1031. // Example:
  1032. //
  1033. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1034. // req.WithQuery("a", 11)
  1035. // req.WithQueryString("b=22&c=33")
  1036. // // URL is now http://example.com/path?a=11&bb=22&c=33
  1037. func (r *Request) WithQueryString(query string) *Request {
  1038. opChain := r.chain.enter("WithQueryString()")
  1039. defer opChain.leave()
  1040. r.mu.Lock()
  1041. defer r.mu.Unlock()
  1042. if opChain.failed() {
  1043. return r
  1044. }
  1045. if !r.checkOrder(opChain, "WithQueryString()") {
  1046. return r
  1047. }
  1048. v, err := url.ParseQuery(query)
  1049. if err != nil {
  1050. opChain.fail(AssertionFailure{
  1051. Type: AssertValid,
  1052. Actual: &AssertionValue{query},
  1053. Errors: []error{
  1054. errors.New("invalid query string"),
  1055. err,
  1056. },
  1057. })
  1058. return r
  1059. }
  1060. if r.query == nil {
  1061. r.query = make(url.Values)
  1062. }
  1063. for k, v := range v {
  1064. r.query[k] = append(r.query[k], v...)
  1065. }
  1066. return r
  1067. }
  1068. // WithURL sets request URL.
  1069. //
  1070. // This URL overwrites Config.BaseURL. Request path passed to request constructor
  1071. // is appended to this URL, separated by slash if necessary.
  1072. //
  1073. // Example:
  1074. //
  1075. // req := NewRequestC(config, "PUT", "/path")
  1076. // req.WithURL("http://example.com")
  1077. // // URL is now http://example.com/path
  1078. func (r *Request) WithURL(urlStr string) *Request {
  1079. opChain := r.chain.enter("WithURL()")
  1080. defer opChain.leave()
  1081. r.mu.Lock()
  1082. defer r.mu.Unlock()
  1083. if opChain.failed() {
  1084. return r
  1085. }
  1086. if !r.checkOrder(opChain, "WithURL()") {
  1087. return r
  1088. }
  1089. u, err := url.Parse(urlStr)
  1090. if err != nil {
  1091. opChain.fail(AssertionFailure{
  1092. Type: AssertValid,
  1093. Actual: &AssertionValue{urlStr},
  1094. Errors: []error{
  1095. errors.New("invalid url string"),
  1096. err,
  1097. },
  1098. })
  1099. return r
  1100. }
  1101. r.httpReq.URL = u
  1102. return r
  1103. }
  1104. // WithHeaders adds given headers to request.
  1105. //
  1106. // Example:
  1107. //
  1108. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1109. // req.WithHeaders(map[string]string{
  1110. // "Content-Type": "application/json",
  1111. // })
  1112. func (r *Request) WithHeaders(headers map[string]string) *Request {
  1113. opChain := r.chain.enter("WithHeaders()")
  1114. defer opChain.leave()
  1115. r.mu.Lock()
  1116. defer r.mu.Unlock()
  1117. if opChain.failed() {
  1118. return r
  1119. }
  1120. if !r.checkOrder(opChain, "WithHeaders()") {
  1121. return r
  1122. }
  1123. for k, v := range headers {
  1124. r.withHeader(k, v)
  1125. }
  1126. return r
  1127. }
  1128. // WithHeader adds given single header to request.
  1129. //
  1130. // Example:
  1131. //
  1132. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1133. // req.WithHeader("Content-Type", "application/json")
  1134. func (r *Request) WithHeader(k, v string) *Request {
  1135. opChain := r.chain.enter("WithHeader()")
  1136. defer opChain.leave()
  1137. r.mu.Lock()
  1138. defer r.mu.Unlock()
  1139. if opChain.failed() {
  1140. return r
  1141. }
  1142. if !r.checkOrder(opChain, "WithHeader()") {
  1143. return r
  1144. }
  1145. r.withHeader(k, v)
  1146. return r
  1147. }
  1148. func (r *Request) withHeader(k, v string) {
  1149. switch http.CanonicalHeaderKey(k) {
  1150. case "Host":
  1151. r.httpReq.Host = v
  1152. case "Content-Type":
  1153. if !r.forceType {
  1154. delete(r.httpReq.Header, "Content-Type")
  1155. }
  1156. r.forceType = true
  1157. r.typeSetter = "WithHeader()"
  1158. r.httpReq.Header.Add(k, v)
  1159. default:
  1160. r.httpReq.Header.Add(k, v)
  1161. }
  1162. }
  1163. // WithCookies adds given cookies to request.
  1164. //
  1165. // Example:
  1166. //
  1167. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1168. // req.WithCookies(map[string]string{
  1169. // "foo": "aa",
  1170. // "bar": "bb",
  1171. // })
  1172. func (r *Request) WithCookies(cookies map[string]string) *Request {
  1173. opChain := r.chain.enter("WithCookies()")
  1174. defer opChain.leave()
  1175. r.mu.Lock()
  1176. defer r.mu.Unlock()
  1177. if opChain.failed() {
  1178. return r
  1179. }
  1180. if !r.checkOrder(opChain, "WithCookies()") {
  1181. return r
  1182. }
  1183. for k, v := range cookies {
  1184. r.httpReq.AddCookie(&http.Cookie{
  1185. Name: k,
  1186. Value: v,
  1187. })
  1188. }
  1189. return r
  1190. }
  1191. // WithCookie adds given single cookie to request.
  1192. //
  1193. // Example:
  1194. //
  1195. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1196. // req.WithCookie("name", "value")
  1197. func (r *Request) WithCookie(k, v string) *Request {
  1198. opChain := r.chain.enter("WithCookie()")
  1199. defer opChain.leave()
  1200. r.mu.Lock()
  1201. defer r.mu.Unlock()
  1202. if opChain.failed() {
  1203. return r
  1204. }
  1205. if !r.checkOrder(opChain, "WithCookie()") {
  1206. return r
  1207. }
  1208. r.httpReq.AddCookie(&http.Cookie{
  1209. Name: k,
  1210. Value: v,
  1211. })
  1212. return r
  1213. }
  1214. // WithBasicAuth sets the request's Authorization header to use HTTP
  1215. // Basic Authentication with the provided username and password.
  1216. //
  1217. // With HTTP Basic Authentication the provided username and password
  1218. // are not encrypted.
  1219. //
  1220. // Example:
  1221. //
  1222. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1223. // req.WithBasicAuth("john", "secret")
  1224. func (r *Request) WithBasicAuth(username, password string) *Request {
  1225. opChain := r.chain.enter("WithBasicAuth()")
  1226. defer opChain.leave()
  1227. r.mu.Lock()
  1228. defer r.mu.Unlock()
  1229. if opChain.failed() {
  1230. return r
  1231. }
  1232. if !r.checkOrder(opChain, "WithBasicAuth()") {
  1233. return r
  1234. }
  1235. r.httpReq.SetBasicAuth(username, password)
  1236. return r
  1237. }
  1238. // WithHost sets request host to given string.
  1239. //
  1240. // Example:
  1241. //
  1242. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1243. // req.WithHost("example.com")
  1244. func (r *Request) WithHost(host string) *Request {
  1245. opChain := r.chain.enter("WithHost()")
  1246. defer opChain.leave()
  1247. r.mu.Lock()
  1248. defer r.mu.Unlock()
  1249. if opChain.failed() {
  1250. return r
  1251. }
  1252. if !r.checkOrder(opChain, "WithHost()") {
  1253. return r
  1254. }
  1255. r.httpReq.Host = host
  1256. return r
  1257. }
  1258. // WithProto sets HTTP protocol version.
  1259. //
  1260. // proto should have form of "HTTP/{major}.{minor}", e.g. "HTTP/1.1".
  1261. //
  1262. // Example:
  1263. //
  1264. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1265. // req.WithProto("HTTP/2.0")
  1266. func (r *Request) WithProto(proto string) *Request {
  1267. opChain := r.chain.enter("WithProto()")
  1268. defer opChain.leave()
  1269. r.mu.Lock()
  1270. defer r.mu.Unlock()
  1271. if opChain.failed() {
  1272. return r
  1273. }
  1274. if !r.checkOrder(opChain, "WithProto()") {
  1275. return r
  1276. }
  1277. major, minor, ok := http.ParseHTTPVersion(proto)
  1278. if !ok {
  1279. opChain.fail(AssertionFailure{
  1280. Type: AssertUsage,
  1281. Errors: []error{
  1282. fmt.Errorf(
  1283. `unexpected protocol version %q, expected "HTTP/{major}.{minor}"`,
  1284. proto),
  1285. },
  1286. })
  1287. return r
  1288. }
  1289. r.httpReq.ProtoMajor = major
  1290. r.httpReq.ProtoMinor = minor
  1291. return r
  1292. }
  1293. // WithChunked enables chunked encoding and sets request body reader.
  1294. //
  1295. // Expect() will read all available data from given reader. Content-Length
  1296. // is not set, and "chunked" Transfer-Encoding is used.
  1297. //
  1298. // If protocol version is not at least HTTP/1.1 (required for chunked
  1299. // encoding), failure is reported.
  1300. //
  1301. // Example:
  1302. //
  1303. // req := NewRequestC(config, "PUT", "http://example.com/upload")
  1304. // fh, _ := os.Open("data")
  1305. // defer fh.Close()
  1306. // req.WithHeader("Content-Type", "application/octet-stream")
  1307. // req.WithChunked(fh)
  1308. func (r *Request) WithChunked(reader io.Reader) *Request {
  1309. opChain := r.chain.enter("WithChunked()")
  1310. defer opChain.leave()
  1311. r.mu.Lock()
  1312. defer r.mu.Unlock()
  1313. if opChain.failed() {
  1314. return r
  1315. }
  1316. if !r.checkOrder(opChain, "WithChunked()") {
  1317. return r
  1318. }
  1319. if !r.httpReq.ProtoAtLeast(1, 1) {
  1320. opChain.fail(AssertionFailure{
  1321. Type: AssertUsage,
  1322. Errors: []error{
  1323. fmt.Errorf(
  1324. `chunked Transfer-Encoding requires at least "HTTP/1.1",`+
  1325. ` but "HTTP/%d.%d" is used`,
  1326. r.httpReq.ProtoMajor, r.httpReq.ProtoMinor),
  1327. },
  1328. })
  1329. return r
  1330. }
  1331. r.setBody(opChain, "WithChunked()", reader, -1, false)
  1332. return r
  1333. }
  1334. // WithBytes sets request body to given slice of bytes.
  1335. //
  1336. // Example:
  1337. //
  1338. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1339. // req.WithHeader("Content-Type", "application/json")
  1340. // req.WithBytes([]byte(`{"foo": 123}`))
  1341. func (r *Request) WithBytes(b []byte) *Request {
  1342. opChain := r.chain.enter("WithBytes()")
  1343. defer opChain.leave()
  1344. r.mu.Lock()
  1345. defer r.mu.Unlock()
  1346. if opChain.failed() {
  1347. return r
  1348. }
  1349. if !r.checkOrder(opChain, "WithBytes()") {
  1350. return r
  1351. }
  1352. if b == nil {
  1353. r.setBody(opChain, "WithBytes()", nil, 0, false)
  1354. } else {
  1355. r.setBody(opChain, "WithBytes()", bytes.NewReader(b), len(b), false)
  1356. }
  1357. return r
  1358. }
  1359. // WithText sets Content-Type header to "text/plain; charset=utf-8" and
  1360. // sets body to given string.
  1361. //
  1362. // Example:
  1363. //
  1364. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1365. // req.WithText("hello, world!")
  1366. func (r *Request) WithText(s string) *Request {
  1367. opChain := r.chain.enter("WithText()")
  1368. defer opChain.leave()
  1369. r.mu.Lock()
  1370. defer r.mu.Unlock()
  1371. if opChain.failed() {
  1372. return r
  1373. }
  1374. if !r.checkOrder(opChain, "WithText()") {
  1375. return r
  1376. }
  1377. r.setType(opChain, "WithText()", "text/plain; charset=utf-8", false)
  1378. r.setBody(opChain, "WithText()", strings.NewReader(s), len(s), false)
  1379. return r
  1380. }
  1381. // WithJSON sets Content-Type header to "application/json; charset=utf-8"
  1382. // and sets body to object, marshaled using json.Marshal().
  1383. //
  1384. // Example:
  1385. //
  1386. // type MyJSON struct {
  1387. // Foo int `json:"foo"`
  1388. // }
  1389. //
  1390. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1391. // req.WithJSON(MyJSON{Foo: 123})
  1392. //
  1393. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1394. // req.WithJSON(map[string]interface{}{"foo": 123})
  1395. func (r *Request) WithJSON(object interface{}) *Request {
  1396. opChain := r.chain.enter("WithJSON()")
  1397. defer opChain.leave()
  1398. r.mu.Lock()
  1399. defer r.mu.Unlock()
  1400. if opChain.failed() {
  1401. return r
  1402. }
  1403. if !r.checkOrder(opChain, "WithJSON()") {
  1404. return r
  1405. }
  1406. b, err := json.Marshal(object)
  1407. if err != nil {
  1408. opChain.fail(AssertionFailure{
  1409. Type: AssertValid,
  1410. Actual: &AssertionValue{object},
  1411. Errors: []error{
  1412. errors.New("invalid json object"),
  1413. err,
  1414. },
  1415. })
  1416. return r
  1417. }
  1418. r.setType(opChain, "WithJSON()", "application/json; charset=utf-8", false)
  1419. r.setBody(opChain, "WithJSON()", bytes.NewReader(b), len(b), false)
  1420. return r
  1421. }
  1422. // WithForm sets Content-Type header to "application/x-www-form-urlencoded"
  1423. // or (if WithMultipart() was called) "multipart/form-data", converts given
  1424. // object to url.Values using github.com/ajg/form, and adds it to request body.
  1425. //
  1426. // Various object types are supported, including maps and structs. Structs may
  1427. // contain "form" struct tag, similar to "json" struct tag for json.Marshal().
  1428. // See https://github.com/ajg/form for details.
  1429. //
  1430. // Multiple WithForm(), WithFormField(), and WithFile() calls may be combined.
  1431. // If WithMultipart() is called, it should be called first.
  1432. //
  1433. // Example:
  1434. //
  1435. // type MyForm struct {
  1436. // Foo int `form:"foo"`
  1437. // }
  1438. //
  1439. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1440. // req.WithForm(MyForm{Foo: 123})
  1441. //
  1442. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1443. // req.WithForm(map[string]interface{}{"foo": 123})
  1444. func (r *Request) WithForm(object interface{}) *Request {
  1445. opChain := r.chain.enter("WithForm()")
  1446. defer opChain.leave()
  1447. r.mu.Lock()
  1448. defer r.mu.Unlock()
  1449. if opChain.failed() {
  1450. return r
  1451. }
  1452. if !r.checkOrder(opChain, "WithForm()") {
  1453. return r
  1454. }
  1455. f, err := form.EncodeToValues(object)
  1456. if err != nil {
  1457. opChain.fail(AssertionFailure{
  1458. Type: AssertValid,
  1459. Actual: &AssertionValue{object},
  1460. Errors: []error{
  1461. errors.New("invalid form object"),
  1462. err,
  1463. },
  1464. })
  1465. return r
  1466. }
  1467. if r.multipart != nil {
  1468. r.setType(opChain, "WithForm()", "multipart/form-data", false)
  1469. var keys []string
  1470. for k := range f {
  1471. keys = append(keys, k)
  1472. }
  1473. sort.Strings(keys)
  1474. for _, k := range keys {
  1475. if err := r.multipart.WriteField(k, f[k][0]); err != nil {
  1476. opChain.fail(AssertionFailure{
  1477. Type: AssertOperation,
  1478. Errors: []error{
  1479. fmt.Errorf("failed to write multipart form field %q", k),
  1480. err,
  1481. },
  1482. })
  1483. return r
  1484. }
  1485. }
  1486. } else {
  1487. r.setType(opChain, "WithForm()", "application/x-www-form-urlencoded", false)
  1488. if r.form == nil {
  1489. r.form = make(url.Values)
  1490. }
  1491. for k, v := range f {
  1492. r.form[k] = append(r.form[k], v...)
  1493. }
  1494. }
  1495. return r
  1496. }
  1497. // WithFormField sets Content-Type header to "application/x-www-form-urlencoded"
  1498. // or (if WithMultipart() was called) "multipart/form-data", converts given
  1499. // value to string using fmt.Sprint(), and adds it to request body.
  1500. //
  1501. // Multiple WithForm(), WithFormField(), and WithFile() calls may be combined.
  1502. // If WithMultipart() is called, it should be called first.
  1503. //
  1504. // Example:
  1505. //
  1506. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1507. // req.WithFormField("foo", 123).
  1508. // WithFormField("bar", 456)
  1509. func (r *Request) WithFormField(key string, value interface{}) *Request {
  1510. opChain := r.chain.enter("WithFormField()")
  1511. defer opChain.leave()
  1512. r.mu.Lock()
  1513. defer r.mu.Unlock()
  1514. if opChain.failed() {
  1515. return r
  1516. }
  1517. if !r.checkOrder(opChain, "WithFormField()") {
  1518. return r
  1519. }
  1520. if r.multipart != nil {
  1521. r.setType(opChain, "WithFormField()", "multipart/form-data", false)
  1522. err := r.multipart.WriteField(key, fmt.Sprint(value))
  1523. if err != nil {
  1524. opChain.fail(AssertionFailure{
  1525. Type: AssertOperation,
  1526. Errors: []error{
  1527. fmt.Errorf("failed to write multipart form field %q", key),
  1528. err,
  1529. },
  1530. })
  1531. return r
  1532. }
  1533. } else {
  1534. r.setType(opChain, "WithFormField()", "application/x-www-form-urlencoded", false)
  1535. if r.form == nil {
  1536. r.form = make(url.Values)
  1537. }
  1538. r.form[key] = append(r.form[key], fmt.Sprint(value))
  1539. }
  1540. return r
  1541. }
  1542. // WithFile sets Content-Type header to "multipart/form-data", reads given
  1543. // file and adds its contents to request body.
  1544. //
  1545. // If reader is given, it's used to read file contents. Otherwise, os.Open()
  1546. // is used to read a file with given path.
  1547. //
  1548. // Multiple WithForm(), WithFormField(), and WithFile() calls may be combined.
  1549. // WithMultipart() should be called before WithFile(), otherwise WithFile()
  1550. // fails.
  1551. //
  1552. // Example:
  1553. //
  1554. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1555. // req.WithFile("avatar", "./john.png")
  1556. //
  1557. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1558. // fh, _ := os.Open("./john.png")
  1559. // req.WithMultipart().
  1560. // WithFile("avatar", "john.png", fh)
  1561. // fh.Close()
  1562. func (r *Request) WithFile(key, path string, reader ...io.Reader) *Request {
  1563. opChain := r.chain.enter("WithFile()")
  1564. defer opChain.leave()
  1565. r.mu.Lock()
  1566. defer r.mu.Unlock()
  1567. if opChain.failed() {
  1568. return r
  1569. }
  1570. if !r.checkOrder(opChain, "WithFile()") {
  1571. return r
  1572. }
  1573. if len(reader) > 1 {
  1574. opChain.fail(AssertionFailure{
  1575. Type: AssertUsage,
  1576. Errors: []error{
  1577. errors.New("unexpected multiple reader arguments"),
  1578. },
  1579. })
  1580. return r
  1581. }
  1582. r.withFile(opChain, "WithFile()", key, path, reader...)
  1583. return r
  1584. }
  1585. // WithFileBytes is like WithFile, but uses given slice of bytes as the
  1586. // file contents.
  1587. //
  1588. // Example:
  1589. //
  1590. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1591. // fh, _ := os.Open("./john.png")
  1592. // b, _ := ioutil.ReadAll(fh)
  1593. // req.WithMultipart().
  1594. // WithFileBytes("avatar", "john.png", b)
  1595. // fh.Close()
  1596. func (r *Request) WithFileBytes(key, path string, data []byte) *Request {
  1597. opChain := r.chain.enter("WithFileBytes()")
  1598. defer opChain.leave()
  1599. r.mu.Lock()
  1600. defer r.mu.Unlock()
  1601. if opChain.failed() {
  1602. return r
  1603. }
  1604. if !r.checkOrder(opChain, "WithFileBytes()") {
  1605. return r
  1606. }
  1607. r.withFile(opChain, "WithFileBytes()", key, path, bytes.NewReader(data))
  1608. return r
  1609. }
  1610. func (r *Request) withFile(
  1611. opChain *chain, method, key, path string, reader ...io.Reader,
  1612. ) {
  1613. r.setType(opChain, method, "multipart/form-data", false)
  1614. if r.multipart == nil {
  1615. opChain.fail(AssertionFailure{
  1616. Type: AssertUsage,
  1617. Errors: []error{
  1618. fmt.Errorf("%s requires WithMultipart() to be called first", method),
  1619. },
  1620. })
  1621. return
  1622. }
  1623. wr, err := r.multipart.CreateFormFile(key, path)
  1624. if err != nil {
  1625. opChain.fail(AssertionFailure{
  1626. Type: AssertOperation,
  1627. Errors: []error{
  1628. fmt.Errorf(
  1629. "failed to create form file with key %q and path %q",
  1630. key, path),
  1631. err,
  1632. },
  1633. })
  1634. return
  1635. }
  1636. var rd io.Reader
  1637. if len(reader) != 0 && reader[0] != nil {
  1638. rd = reader[0]
  1639. } else {
  1640. f, err := os.Open(path)
  1641. if err != nil {
  1642. opChain.fail(AssertionFailure{
  1643. Type: AssertOperation,
  1644. Errors: []error{
  1645. fmt.Errorf("failed to open file %q", path),
  1646. err,
  1647. },
  1648. })
  1649. return
  1650. }
  1651. rd = f
  1652. defer f.Close()
  1653. }
  1654. if _, err := io.Copy(wr, rd); err != nil {
  1655. opChain.fail(AssertionFailure{
  1656. Type: AssertOperation,
  1657. Errors: []error{
  1658. fmt.Errorf("failed to read file %q", path),
  1659. err,
  1660. },
  1661. })
  1662. return
  1663. }
  1664. }
  1665. // WithMultipart sets Content-Type header to "multipart/form-data".
  1666. //
  1667. // After this call, WithForm() and WithFormField() switch to multipart
  1668. // form instead of urlencoded form.
  1669. //
  1670. // If WithMultipart() is called, it should be called before WithForm(),
  1671. // WithFormField(), and WithFile().
  1672. //
  1673. // WithFile() always requires WithMultipart() to be called first.
  1674. //
  1675. // Example:
  1676. //
  1677. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1678. // req.WithMultipart().
  1679. // WithForm(map[string]interface{}{"foo": 123})
  1680. func (r *Request) WithMultipart() *Request {
  1681. opChain := r.chain.enter("WithMultipart()")
  1682. defer opChain.leave()
  1683. r.mu.Lock()
  1684. defer r.mu.Unlock()
  1685. if opChain.failed() {
  1686. return r
  1687. }
  1688. if !r.checkOrder(opChain, "WithMultipart()") {
  1689. return r
  1690. }
  1691. r.setType(opChain, "WithMultipart()", "multipart/form-data", false)
  1692. if r.multipart == nil {
  1693. r.formbuf = &bytes.Buffer{}
  1694. r.multipart = r.multipartFn(r.formbuf)
  1695. r.setBody(opChain, "WithMultipart()", r.formbuf, 0, false)
  1696. }
  1697. return r
  1698. }
  1699. // Expect constructs http.Request, sends it, receives http.Response, and
  1700. // returns a new Response instance.
  1701. //
  1702. // Request is sent using Client interface, or WebsocketDialer in case of
  1703. // WebSocket request.
  1704. //
  1705. // After calling Expect, there should not be any more calls of Expect or
  1706. // other WithXXX methods on the same Request instance.
  1707. //
  1708. // Example:
  1709. //
  1710. // req := NewRequestC(config, "PUT", "http://example.com/path")
  1711. // req.WithJSON(map[string]interface{}{"foo": 123})
  1712. // resp := req.Expect()
  1713. // resp.Status(http.StatusOK)
  1714. func (r *Request) Expect() *Response {
  1715. opChain := r.chain.enter("Expect()")
  1716. defer opChain.leave()
  1717. resp := r.expect(opChain)
  1718. if resp == nil {
  1719. resp = newResponse(responseOpts{
  1720. config: r.config,
  1721. chain: opChain,
  1722. })
  1723. }
  1724. return resp
  1725. }
  1726. func (r *Request) expect(opChain *chain) *Response {
  1727. if !r.prepare(opChain) {
  1728. return nil
  1729. }
  1730. // after return from prepare(), all subsequent calls to WithXXX and Expect will
  1731. // abort early due to checkOrder(); so we can safely proceed without a lock
  1732. resp := r.execute(opChain)
  1733. if resp == nil {
  1734. return nil
  1735. }
  1736. for _, matcher := range r.matchers {
  1737. matcher(resp)
  1738. }
  1739. return resp
  1740. }
  1741. func (r *Request) prepare(opChain *chain) bool {
  1742. r.mu.Lock()
  1743. defer r.mu.Unlock()
  1744. if opChain.failed() {
  1745. return false
  1746. }
  1747. if !r.checkOrder(opChain, "Expect()") {
  1748. return false
  1749. }
  1750. r.expectCalled = true
  1751. return true
  1752. }
  1753. func (r *Request) execute(opChain *chain) *Response {
  1754. if !r.encodeRequest(opChain) {
  1755. return nil
  1756. }
  1757. if r.wsUpgrade {
  1758. if !r.encodeWebsocketRequest(opChain) {
  1759. return nil
  1760. }
  1761. }
  1762. for _, transform := range r.transformers {
  1763. transform(r.httpReq)
  1764. if opChain.failed() {
  1765. return nil
  1766. }
  1767. }
  1768. var (
  1769. httpResp *http.Response
  1770. websock *websocket.Conn
  1771. elapsed time.Duration
  1772. )
  1773. if r.wsUpgrade {
  1774. httpResp, websock, elapsed = r.sendWebsocketRequest(opChain)
  1775. } else {
  1776. httpResp, elapsed = r.sendRequest(opChain)
  1777. }
  1778. if httpResp == nil {
  1779. return nil
  1780. }
  1781. return newResponse(responseOpts{
  1782. config: r.config,
  1783. chain: opChain,
  1784. httpResp: httpResp,
  1785. websocket: websock,
  1786. rtt: []time.Duration{elapsed},
  1787. })
  1788. }
  1789. func (r *Request) encodeRequest(opChain *chain) bool {
  1790. r.httpReq.URL.Path = concatPaths(r.httpReq.URL.Path, r.path)
  1791. if r.query != nil {
  1792. r.httpReq.URL.RawQuery = r.query.Encode()
  1793. }
  1794. if r.multipart != nil {
  1795. if err := r.multipart.Close(); err != nil {
  1796. opChain.fail(AssertionFailure{
  1797. Type: AssertOperation,
  1798. Errors: []error{
  1799. errors.New("failed to close multipart form"),
  1800. err,
  1801. },
  1802. })
  1803. return false
  1804. }
  1805. r.setType(opChain, "Expect()", r.multipart.FormDataContentType(), true)
  1806. r.setBody(opChain, "Expect()", r.formbuf, r.formbuf.Len(), true)
  1807. } else if r.form != nil {
  1808. s := r.form.Encode()
  1809. r.setBody(opChain,
  1810. "WithForm() or WithFormField()", strings.NewReader(s), len(s), false)
  1811. }
  1812. if r.httpReq.Body == nil {
  1813. r.httpReq.Body = http.NoBody
  1814. }
  1815. if r.config.Context != nil {
  1816. r.httpReq = r.httpReq.WithContext(r.config.Context)
  1817. }
  1818. r.setupRedirects(opChain)
  1819. return true
  1820. }
  1821. var websocketErr = `webocket request can not have body:
  1822. body was set by %s
  1823. webocket was enabled by WithWebsocketUpgrade()`
  1824. func (r *Request) encodeWebsocketRequest(opChain *chain) bool {
  1825. if r.bodySetter != "" {
  1826. opChain.fail(AssertionFailure{
  1827. Type: AssertUsage,
  1828. Errors: []error{
  1829. fmt.Errorf(websocketErr, r.bodySetter),
  1830. },
  1831. })
  1832. return false
  1833. }
  1834. switch r.httpReq.URL.Scheme {
  1835. case "https":
  1836. r.httpReq.URL.Scheme = "wss"
  1837. default:
  1838. r.httpReq.URL.Scheme = "ws"
  1839. }
  1840. return true
  1841. }
  1842. func (r *Request) sendRequest(opChain *chain) (*http.Response, time.Duration) {
  1843. resp, elapsed, err := r.retryRequest(func() (*http.Response, error) {
  1844. return r.config.Client.Do(r.httpReq)
  1845. })
  1846. if err != nil {
  1847. opChain.fail(AssertionFailure{
  1848. Type: AssertOperation,
  1849. Errors: []error{
  1850. errors.New("failed to send http request"),
  1851. err,
  1852. },
  1853. })
  1854. return nil, 0
  1855. }
  1856. return resp, elapsed
  1857. }
  1858. func (r *Request) sendWebsocketRequest(opChain *chain) (
  1859. *http.Response, *websocket.Conn, time.Duration,
  1860. ) {
  1861. var conn *websocket.Conn
  1862. resp, elapsed, err := r.retryRequest(func() (resp *http.Response, err error) {
  1863. conn, resp, err = r.config.WebsocketDialer.Dial(
  1864. r.httpReq.URL.String(), r.httpReq.Header)
  1865. return resp, err
  1866. })
  1867. if err != nil && err != websocket.ErrBadHandshake {
  1868. opChain.fail(AssertionFailure{
  1869. Type: AssertOperation,
  1870. Errors: []error{
  1871. errors.New("failed to send websocket request"),
  1872. err,
  1873. },
  1874. })
  1875. return nil, nil, 0
  1876. }
  1877. if conn == nil {
  1878. opChain.fail(AssertionFailure{
  1879. Type: AssertOperation,
  1880. Errors: []error{
  1881. errors.New("failed to upgrade connection to websocket"),
  1882. },
  1883. })
  1884. return nil, nil, 0
  1885. }
  1886. return resp, conn, elapsed
  1887. }
  1888. func (r *Request) retryRequest(reqFunc func() (*http.Response, error)) (
  1889. *http.Response, time.Duration, error,
  1890. ) {
  1891. if r.httpReq.Body != nil && r.httpReq.Body != http.NoBody {
  1892. if _, ok := r.httpReq.Body.(*bodyWrapper); !ok {
  1893. r.httpReq.Body = newBodyWrapper(r.httpReq.Body, nil)
  1894. }
  1895. }
  1896. reqBody, _ := r.httpReq.Body.(*bodyWrapper)
  1897. delay := r.minRetryDelay
  1898. i := 0
  1899. for {
  1900. for _, printer := range r.config.Printers {
  1901. if reqBody != nil {
  1902. reqBody.Rewind()
  1903. }
  1904. printer.Request(r.httpReq)
  1905. }
  1906. if reqBody != nil {
  1907. reqBody.Rewind()
  1908. }
  1909. var cancelFn context.CancelFunc
  1910. if r.timeout > 0 {
  1911. var ctx context.Context
  1912. if r.config.Context != nil {
  1913. ctx, cancelFn = context.WithTimeout(r.config.Context, r.timeout)
  1914. } else {
  1915. ctx, cancelFn = context.WithTimeout(context.Background(), r.timeout)
  1916. }
  1917. r.httpReq = r.httpReq.WithContext(ctx)
  1918. }
  1919. start := time.Now()
  1920. resp, err := reqFunc()
  1921. elapsed := time.Since(start)
  1922. if resp != nil && resp.Body != nil {
  1923. resp.Body = newBodyWrapper(resp.Body, cancelFn)
  1924. } else if cancelFn != nil {
  1925. cancelFn()
  1926. }
  1927. if resp != nil {
  1928. for _, printer := range r.config.Printers {
  1929. if resp.Body != nil {
  1930. resp.Body.(*bodyWrapper).Rewind()
  1931. }
  1932. printer.Response(resp, elapsed)
  1933. }
  1934. }
  1935. i++
  1936. if i == r.maxRetries+1 {
  1937. return resp, elapsed, err
  1938. }
  1939. if !r.shouldRetry(resp, err) {
  1940. return resp, elapsed, err
  1941. }
  1942. if resp != nil && resp.Body != nil {
  1943. resp.Body.Close()
  1944. }
  1945. if configCtx := r.config.Context; configCtx != nil {
  1946. select {
  1947. case <-configCtx.Done():
  1948. return nil, elapsed, configCtx.Err()
  1949. case <-r.sleepFn(delay):
  1950. }
  1951. } else {
  1952. <-r.sleepFn(delay)
  1953. }
  1954. delay *= 2
  1955. if delay > r.maxRetryDelay {
  1956. delay = r.maxRetryDelay
  1957. }
  1958. }
  1959. }
  1960. func (r *Request) shouldRetry(resp *http.Response, err error) bool {
  1961. var (
  1962. isTemporaryNetworkError bool // Deprecated
  1963. isTimeoutError bool
  1964. isServerError bool
  1965. isHTTPError bool
  1966. )
  1967. if netErr, ok := err.(net.Error); ok {
  1968. //nolint
  1969. isTemporaryNetworkError = netErr.Temporary()
  1970. isTimeoutError = netErr.Timeout()
  1971. }
  1972. if resp != nil {
  1973. isServerError = resp.StatusCode >= 500 && resp.StatusCode <= 599
  1974. isHTTPError = resp.StatusCode >= 400 && resp.StatusCode <= 599
  1975. }
  1976. switch r.retryPolicy {
  1977. case DontRetry:
  1978. break
  1979. case RetryTemporaryNetworkErrors:
  1980. return isTemporaryNetworkError
  1981. case RetryTemporaryNetworkAndServerErrors:
  1982. return isTemporaryNetworkError || isServerError
  1983. case RetryTimeoutErrors:
  1984. return isTimeoutError
  1985. case RetryTimeoutAndServerErrors:
  1986. return isTimeoutError || isServerError
  1987. case RetryAllErrors:
  1988. return err != nil || isHTTPError
  1989. }
  1990. return false
  1991. }
  1992. func (r *Request) setupRedirects(opChain *chain) {
  1993. httpClient, _ := r.config.Client.(*http.Client)
  1994. if httpClient == nil {
  1995. if r.redirectPolicy != defaultRedirectPolicy {
  1996. opChain.fail(AssertionFailure{
  1997. Type: AssertUsage,
  1998. Errors: []error{
  1999. errors.New(
  2000. "WithRedirectPolicy() can be used only if Client is *http.Client"),
  2001. },
  2002. })
  2003. return
  2004. }
  2005. if r.maxRedirects != -1 {
  2006. opChain.fail(AssertionFailure{
  2007. Type: AssertUsage,
  2008. Errors: []error{
  2009. errors.New(
  2010. "WithMaxRedirects() can be used only if Client is *http.Client"),
  2011. },
  2012. })
  2013. return
  2014. }
  2015. } else {
  2016. if r.redirectPolicy != defaultRedirectPolicy || r.maxRedirects != -1 {
  2017. clientCopy := *httpClient
  2018. httpClient = &clientCopy
  2019. r.config.Client = &clientCopy
  2020. }
  2021. }
  2022. if r.redirectPolicy == DontFollowRedirects {
  2023. httpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
  2024. return http.ErrUseLastResponse
  2025. }
  2026. } else if r.maxRedirects >= 0 {
  2027. httpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
  2028. if len(via) > r.maxRedirects {
  2029. return fmt.Errorf("stopped after %d redirects", r.maxRedirects)
  2030. }
  2031. return nil
  2032. }
  2033. } else if r.redirectPolicy != defaultRedirectPolicy {
  2034. httpClient.CheckRedirect = nil
  2035. }
  2036. if r.redirectPolicy == FollowAllRedirects {
  2037. if r.httpReq.Body != nil && r.httpReq.Body != http.NoBody {
  2038. if _, ok := r.httpReq.Body.(*bodyWrapper); !ok {
  2039. r.httpReq.Body = newBodyWrapper(r.httpReq.Body, nil)
  2040. }
  2041. r.httpReq.GetBody = r.httpReq.Body.(*bodyWrapper).GetBody
  2042. } else {
  2043. r.httpReq.GetBody = func() (io.ReadCloser, error) {
  2044. return http.NoBody, nil
  2045. }
  2046. }
  2047. } else if r.redirectPolicy != defaultRedirectPolicy {
  2048. r.httpReq.GetBody = nil
  2049. }
  2050. }
  2051. var typeErr = `ambiguous request "Content-Type" header values:
  2052. first set by %s:
  2053. %q
  2054. then replaced by %s:
  2055. %q`
  2056. func (r *Request) setType(
  2057. opChain *chain, newSetter, newType string, overwrite bool,
  2058. ) {
  2059. if r.forceType {
  2060. return
  2061. }
  2062. if !overwrite {
  2063. previousType := r.httpReq.Header.Get("Content-Type")
  2064. if previousType != "" && previousType != newType {
  2065. opChain.fail(AssertionFailure{
  2066. Type: AssertUsage,
  2067. Errors: []error{
  2068. fmt.Errorf(typeErr,
  2069. r.typeSetter, previousType, newSetter, newType),
  2070. },
  2071. })
  2072. return
  2073. }
  2074. }
  2075. r.typeSetter = newSetter
  2076. r.httpReq.Header["Content-Type"] = []string{newType}
  2077. }
  2078. var bodyErr = `ambiguous request body contents:
  2079. first set by %s
  2080. then replaced by %s`
  2081. func (r *Request) setBody(
  2082. opChain *chain, setter string, reader io.Reader, len int, overwrite bool,
  2083. ) {
  2084. if !overwrite && r.bodySetter != "" {
  2085. opChain.fail(AssertionFailure{
  2086. Type: AssertUsage,
  2087. Errors: []error{
  2088. fmt.Errorf(bodyErr, r.bodySetter, setter),
  2089. },
  2090. })
  2091. return
  2092. }
  2093. if len > 0 && reader == nil {
  2094. panic("invalid length")
  2095. }
  2096. if reader == nil {
  2097. r.httpReq.Body = http.NoBody
  2098. r.httpReq.ContentLength = 0
  2099. } else {
  2100. r.httpReq.Body = ioutil.NopCloser(reader)
  2101. r.httpReq.ContentLength = int64(len)
  2102. }
  2103. r.bodySetter = setter
  2104. }
  2105. func (r *Request) checkOrder(opChain *chain, funcCall string) bool {
  2106. if r.expectCalled {
  2107. opChain.fail(AssertionFailure{
  2108. Type: AssertUsage,
  2109. Errors: []error{
  2110. fmt.Errorf("unexpected call to %s: Expect() has already been called", funcCall),
  2111. },
  2112. })
  2113. return false
  2114. }
  2115. return true
  2116. }
  2117. func concatPaths(a, b string) string {
  2118. if a == "" {
  2119. return b
  2120. }
  2121. if b == "" {
  2122. return a
  2123. }
  2124. a = strings.TrimSuffix(a, "/")
  2125. b = strings.TrimPrefix(b, "/")
  2126. return a + "/" + b
  2127. }
  2128. func mustWrite(w io.Writer, s string) {
  2129. _, err := w.Write([]byte(s))
  2130. if err != nil {
  2131. panic(err)
  2132. }
  2133. }