client.go 87 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192
  1. package fasthttp
  2. import (
  3. "bufio"
  4. "bytes"
  5. "crypto/tls"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "net"
  10. "strings"
  11. "sync"
  12. "sync/atomic"
  13. "time"
  14. )
  15. // Do performs the given http request and fills the given http response.
  16. //
  17. // Request must contain at least non-zero RequestURI with full url (including
  18. // scheme and host) or non-zero Host header + RequestURI.
  19. //
  20. // Client determines the server to be requested in the following order:
  21. //
  22. // - from RequestURI if it contains full url with scheme and host;
  23. // - from Host header otherwise.
  24. //
  25. // The function doesn't follow redirects. Use Get* for following redirects.
  26. //
  27. // Response is ignored if resp is nil.
  28. //
  29. // ErrNoFreeConns is returned if all DefaultMaxConnsPerHost connections
  30. // to the requested host are busy.
  31. //
  32. // It is recommended obtaining req and resp via AcquireRequest
  33. // and AcquireResponse in performance-critical code.
  34. func Do(req *Request, resp *Response) error {
  35. return defaultClient.Do(req, resp)
  36. }
  37. // DoTimeout performs the given request and waits for response during
  38. // the given timeout duration.
  39. //
  40. // Request must contain at least non-zero RequestURI with full url (including
  41. // scheme and host) or non-zero Host header + RequestURI.
  42. //
  43. // Client determines the server to be requested in the following order:
  44. //
  45. // - from RequestURI if it contains full url with scheme and host;
  46. // - from Host header otherwise.
  47. //
  48. // The function doesn't follow redirects. Use Get* for following redirects.
  49. //
  50. // Response is ignored if resp is nil.
  51. //
  52. // ErrTimeout is returned if the response wasn't returned during
  53. // the given timeout.
  54. //
  55. // ErrNoFreeConns is returned if all DefaultMaxConnsPerHost connections
  56. // to the requested host are busy.
  57. //
  58. // It is recommended obtaining req and resp via AcquireRequest
  59. // and AcquireResponse in performance-critical code.
  60. func DoTimeout(req *Request, resp *Response, timeout time.Duration) error {
  61. return defaultClient.DoTimeout(req, resp, timeout)
  62. }
  63. // DoDeadline performs the given request and waits for response until
  64. // the given deadline.
  65. //
  66. // Request must contain at least non-zero RequestURI with full url (including
  67. // scheme and host) or non-zero Host header + RequestURI.
  68. //
  69. // Client determines the server to be requested in the following order:
  70. //
  71. // - from RequestURI if it contains full url with scheme and host;
  72. // - from Host header otherwise.
  73. //
  74. // The function doesn't follow redirects. Use Get* for following redirects.
  75. //
  76. // Response is ignored if resp is nil.
  77. //
  78. // ErrTimeout is returned if the response wasn't returned until
  79. // the given deadline.
  80. //
  81. // ErrNoFreeConns is returned if all DefaultMaxConnsPerHost connections
  82. // to the requested host are busy.
  83. //
  84. // It is recommended obtaining req and resp via AcquireRequest
  85. // and AcquireResponse in performance-critical code.
  86. func DoDeadline(req *Request, resp *Response, deadline time.Time) error {
  87. return defaultClient.DoDeadline(req, resp, deadline)
  88. }
  89. // DoRedirects performs the given http request and fills the given http response,
  90. // following up to maxRedirectsCount redirects. When the redirect count exceeds
  91. // maxRedirectsCount, ErrTooManyRedirects is returned.
  92. //
  93. // Request must contain at least non-zero RequestURI with full url (including
  94. // scheme and host) or non-zero Host header + RequestURI.
  95. //
  96. // Client determines the server to be requested in the following order:
  97. //
  98. // - from RequestURI if it contains full url with scheme and host;
  99. // - from Host header otherwise.
  100. //
  101. // Response is ignored if resp is nil.
  102. //
  103. // ErrNoFreeConns is returned if all DefaultMaxConnsPerHost connections
  104. // to the requested host are busy.
  105. //
  106. // It is recommended obtaining req and resp via AcquireRequest
  107. // and AcquireResponse in performance-critical code.
  108. func DoRedirects(req *Request, resp *Response, maxRedirectsCount int) error {
  109. if defaultClient.DisablePathNormalizing {
  110. req.URI().DisablePathNormalizing = true
  111. }
  112. _, _, err := doRequestFollowRedirects(req, resp, req.URI().String(), maxRedirectsCount, &defaultClient)
  113. return err
  114. }
  115. // Get returns the status code and body of url.
  116. //
  117. // The contents of dst will be replaced by the body and returned, if the dst
  118. // is too small a new slice will be allocated.
  119. //
  120. // The function follows redirects. Use Do* for manually handling redirects.
  121. func Get(dst []byte, url string) (statusCode int, body []byte, err error) {
  122. return defaultClient.Get(dst, url)
  123. }
  124. // GetTimeout returns the status code and body of url.
  125. //
  126. // The contents of dst will be replaced by the body and returned, if the dst
  127. // is too small a new slice will be allocated.
  128. //
  129. // The function follows redirects. Use Do* for manually handling redirects.
  130. //
  131. // ErrTimeout error is returned if url contents couldn't be fetched
  132. // during the given timeout.
  133. func GetTimeout(dst []byte, url string, timeout time.Duration) (statusCode int, body []byte, err error) {
  134. return defaultClient.GetTimeout(dst, url, timeout)
  135. }
  136. // GetDeadline returns the status code and body of url.
  137. //
  138. // The contents of dst will be replaced by the body and returned, if the dst
  139. // is too small a new slice will be allocated.
  140. //
  141. // The function follows redirects. Use Do* for manually handling redirects.
  142. //
  143. // ErrTimeout error is returned if url contents couldn't be fetched
  144. // until the given deadline.
  145. func GetDeadline(dst []byte, url string, deadline time.Time) (statusCode int, body []byte, err error) {
  146. return defaultClient.GetDeadline(dst, url, deadline)
  147. }
  148. // Post sends POST request to the given url with the given POST arguments.
  149. //
  150. // The contents of dst will be replaced by the body and returned, if the dst
  151. // is too small a new slice will be allocated.
  152. //
  153. // The function follows redirects. Use Do* for manually handling redirects.
  154. //
  155. // Empty POST body is sent if postArgs is nil.
  156. func Post(dst []byte, url string, postArgs *Args) (statusCode int, body []byte, err error) {
  157. return defaultClient.Post(dst, url, postArgs)
  158. }
  159. var defaultClient Client
  160. // Client implements http client.
  161. //
  162. // Copying Client by value is prohibited. Create new instance instead.
  163. //
  164. // It is safe calling Client methods from concurrently running goroutines.
  165. //
  166. // The fields of a Client should not be changed while it is in use.
  167. type Client struct {
  168. noCopy noCopy
  169. readerPool sync.Pool
  170. writerPool sync.Pool
  171. // Transport defines a transport-like mechanism that wraps every request/response.
  172. Transport RoundTripper
  173. // Callback for establishing new connections to hosts.
  174. //
  175. // Default DialTimeout is used if not set.
  176. DialTimeout DialFuncWithTimeout
  177. // Callback for establishing new connections to hosts.
  178. //
  179. // Note that if Dial is set instead of DialTimeout, Dial will ignore Request timeout.
  180. // If you want the tcp dial process to account for request timeouts, use DialTimeout instead.
  181. //
  182. // If not set, DialTimeout is used.
  183. Dial DialFunc
  184. // TLS config for https connections.
  185. //
  186. // Default TLS config is used if not set.
  187. TLSConfig *tls.Config
  188. // RetryIf controls whether a retry should be attempted after an error.
  189. //
  190. // By default will use isIdempotent function.
  191. //
  192. // Deprecated: Use RetryIfErr instead.
  193. // This field is only effective when the `RetryIfErr` field is not set.
  194. RetryIf RetryIfFunc
  195. // When the client encounters an error during a request, the behavior—whether to retry
  196. // and whether to reset the request timeout—should be determined
  197. // based on the return value of this field.
  198. // This field is only effective within the range of MaxIdemponentCallAttempts.
  199. RetryIfErr RetryIfErrFunc
  200. // RetryIfErrUpstream works just like RetryIfErr but also provides information about which upstream caused the error, if known.
  201. // Upstream information is a <host>:<port> format.
  202. RetryIfErrUpstream RetryIfErrUpstreamFunc
  203. // ConfigureClient configures the fasthttp.HostClient.
  204. ConfigureClient func(hc *HostClient) error
  205. m map[string]*HostClient
  206. ms map[string]*HostClient
  207. // Client name. Used in User-Agent request header.
  208. //
  209. // Default client name is used if not set.
  210. Name string
  211. // Maximum number of connections per each host which may be established.
  212. //
  213. // DefaultMaxConnsPerHost is used if not set.
  214. MaxConnsPerHost int
  215. // Idle keep-alive connections are closed after this duration.
  216. //
  217. // By default idle connections are closed
  218. // after DefaultMaxIdleConnDuration.
  219. MaxIdleConnDuration time.Duration
  220. // Keep-alive connections are closed after this duration.
  221. //
  222. // By default connection duration is unlimited.
  223. MaxConnDuration time.Duration
  224. // Maximum number of attempts for idempotent calls.
  225. //
  226. // DefaultMaxIdemponentCallAttempts is used if not set.
  227. MaxIdemponentCallAttempts int
  228. // Per-connection buffer size for responses' reading.
  229. // This also limits the maximum header size.
  230. //
  231. // Default buffer size is used if 0.
  232. ReadBufferSize int
  233. // Per-connection buffer size for requests' writing.
  234. //
  235. // Default buffer size is used if 0.
  236. WriteBufferSize int
  237. // Maximum duration for full response reading (including body).
  238. //
  239. // By default response read timeout is unlimited.
  240. ReadTimeout time.Duration
  241. // Maximum duration for full request writing (including body).
  242. //
  243. // By default request write timeout is unlimited.
  244. WriteTimeout time.Duration
  245. // Maximum response body size.
  246. //
  247. // The client returns ErrBodyTooLarge if this limit is greater than 0
  248. // and response body is greater than the limit.
  249. //
  250. // By default response body size is unlimited.
  251. //
  252. // Note that if StreamResponseBody is true, MaxResponseBodySize is ignored.
  253. MaxResponseBodySize int
  254. // Maximum duration for waiting for a free connection.
  255. //
  256. // By default will not waiting, return ErrNoFreeConns immediately.
  257. MaxConnWaitTimeout time.Duration
  258. // Connection pool strategy. Can be either LIFO or FIFO (default).
  259. ConnPoolStrategy ConnPoolStrategyType
  260. mLock sync.RWMutex
  261. mOnce sync.Once
  262. // NoDefaultUserAgentHeader when set to true, causes the default
  263. // User-Agent header to be excluded from the Request.
  264. NoDefaultUserAgentHeader bool
  265. // Attempt to connect to both ipv4 and ipv6 addresses if set to true.
  266. //
  267. // This option is used only if default TCP dialer is used,
  268. // i.e. if Dial is blank.
  269. //
  270. // By default client connects only to ipv4 addresses,
  271. // since unfortunately ipv6 remains broken in many networks worldwide :)
  272. DialDualStack bool
  273. // Header names are passed as-is without normalization
  274. // if this option is set.
  275. //
  276. // Disabled header names' normalization may be useful only for proxying
  277. // responses to other clients expecting case-sensitive
  278. // header names. See https://github.com/valyala/fasthttp/issues/57
  279. // for details.
  280. //
  281. // By default request and response header names are normalized, i.e.
  282. // The first letter and the first letters following dashes
  283. // are uppercased, while all the other letters are lowercased.
  284. // Examples:
  285. //
  286. // * HOST -> Host
  287. // * content-type -> Content-Type
  288. // * cONTENT-lenGTH -> Content-Length
  289. DisableHeaderNamesNormalizing bool
  290. // Path values are sent as-is without normalization.
  291. //
  292. // Disabled path normalization may be useful for proxying incoming requests
  293. // to servers that are expecting paths to be forwarded as-is.
  294. //
  295. // By default path values are normalized, i.e.
  296. // extra slashes are removed, special characters are encoded.
  297. DisablePathNormalizing bool
  298. // StreamResponseBody enables response body streaming.
  299. StreamResponseBody bool
  300. }
  301. // Get returns the status code and body of url.
  302. //
  303. // The contents of dst will be replaced by the body and returned, if the dst
  304. // is too small a new slice will be allocated.
  305. //
  306. // The function follows redirects. Use Do* for manually handling redirects.
  307. func (c *Client) Get(dst []byte, url string) (statusCode int, body []byte, err error) {
  308. return clientGetURL(dst, url, c)
  309. }
  310. // GetTimeout returns the status code and body of url.
  311. //
  312. // The contents of dst will be replaced by the body and returned, if the dst
  313. // is too small a new slice will be allocated.
  314. //
  315. // The function follows redirects. Use Do* for manually handling redirects.
  316. //
  317. // ErrTimeout error is returned if url contents couldn't be fetched
  318. // during the given timeout.
  319. func (c *Client) GetTimeout(dst []byte, url string, timeout time.Duration) (statusCode int, body []byte, err error) {
  320. return clientGetURLTimeout(dst, url, timeout, c)
  321. }
  322. // GetDeadline returns the status code and body of url.
  323. //
  324. // The contents of dst will be replaced by the body and returned, if the dst
  325. // is too small a new slice will be allocated.
  326. //
  327. // The function follows redirects. Use Do* for manually handling redirects.
  328. //
  329. // ErrTimeout error is returned if url contents couldn't be fetched
  330. // until the given deadline.
  331. func (c *Client) GetDeadline(dst []byte, url string, deadline time.Time) (statusCode int, body []byte, err error) {
  332. return clientGetURLDeadline(dst, url, deadline, c)
  333. }
  334. // Post sends POST request to the given url with the given POST arguments.
  335. //
  336. // The contents of dst will be replaced by the body and returned, if the dst
  337. // is too small a new slice will be allocated.
  338. //
  339. // The function follows redirects. Use Do* for manually handling redirects.
  340. //
  341. // Empty POST body is sent if postArgs is nil.
  342. func (c *Client) Post(dst []byte, url string, postArgs *Args) (statusCode int, body []byte, err error) {
  343. return clientPostURL(dst, url, postArgs, c)
  344. }
  345. // DoTimeout performs the given request and waits for response during
  346. // the given timeout duration.
  347. //
  348. // Request must contain at least non-zero RequestURI with full url (including
  349. // scheme and host) or non-zero Host header + RequestURI.
  350. //
  351. // Client determines the server to be requested in the following order:
  352. //
  353. // - from RequestURI if it contains full url with scheme and host;
  354. // - from Host header otherwise.
  355. //
  356. // The function doesn't follow redirects. Use Get* for following redirects.
  357. //
  358. // Response is ignored if resp is nil.
  359. //
  360. // ErrTimeout is returned if the response wasn't returned during
  361. // the given timeout.
  362. // Immediately returns ErrTimeout if timeout value is negative.
  363. //
  364. // ErrNoFreeConns is returned if all Client.MaxConnsPerHost connections
  365. // to the requested host are busy.
  366. //
  367. // It is recommended obtaining req and resp via AcquireRequest
  368. // and AcquireResponse in performance-critical code.
  369. func (c *Client) DoTimeout(req *Request, resp *Response, timeout time.Duration) error {
  370. req.timeout = timeout
  371. if req.timeout <= 0 {
  372. return ErrTimeout
  373. }
  374. return c.Do(req, resp)
  375. }
  376. // DoDeadline performs the given request and waits for response until
  377. // the given deadline.
  378. //
  379. // Request must contain at least non-zero RequestURI with full url (including
  380. // scheme and host) or non-zero Host header + RequestURI.
  381. //
  382. // Client determines the server to be requested in the following order:
  383. //
  384. // - from RequestURI if it contains full url with scheme and host;
  385. // - from Host header otherwise.
  386. //
  387. // The function doesn't follow redirects. Use Get* for following redirects.
  388. //
  389. // Response is ignored if resp is nil.
  390. //
  391. // ErrTimeout is returned if the response wasn't returned until
  392. // the given deadline.
  393. // Immediately returns ErrTimeout if the deadline has already been reached.
  394. //
  395. // ErrNoFreeConns is returned if all Client.MaxConnsPerHost connections
  396. // to the requested host are busy.
  397. //
  398. // It is recommended obtaining req and resp via AcquireRequest
  399. // and AcquireResponse in performance-critical code.
  400. func (c *Client) DoDeadline(req *Request, resp *Response, deadline time.Time) error {
  401. req.timeout = time.Until(deadline)
  402. if req.timeout <= 0 {
  403. return ErrTimeout
  404. }
  405. return c.Do(req, resp)
  406. }
  407. // DoRedirects performs the given http request and fills the given http response,
  408. // following up to maxRedirectsCount redirects. When the redirect count exceeds
  409. // maxRedirectsCount, ErrTooManyRedirects is returned.
  410. //
  411. // Request must contain at least non-zero RequestURI with full url (including
  412. // scheme and host) or non-zero Host header + RequestURI.
  413. //
  414. // Client determines the server to be requested in the following order:
  415. //
  416. // - from RequestURI if it contains full url with scheme and host;
  417. // - from Host header otherwise.
  418. //
  419. // Response is ignored if resp is nil.
  420. //
  421. // ErrNoFreeConns is returned if all DefaultMaxConnsPerHost connections
  422. // to the requested host are busy.
  423. //
  424. // It is recommended obtaining req and resp via AcquireRequest
  425. // and AcquireResponse in performance-critical code.
  426. func (c *Client) DoRedirects(req *Request, resp *Response, maxRedirectsCount int) error {
  427. if c.DisablePathNormalizing {
  428. req.URI().DisablePathNormalizing = true
  429. }
  430. _, _, err := doRequestFollowRedirects(req, resp, req.URI().String(), maxRedirectsCount, c)
  431. return err
  432. }
  433. // Do performs the given http request and fills the given http response.
  434. //
  435. // Request must contain at least non-zero RequestURI with full url (including
  436. // scheme and host) or non-zero Host header + RequestURI.
  437. //
  438. // Client determines the server to be requested in the following order:
  439. //
  440. // - from RequestURI if it contains full url with scheme and host;
  441. // - from Host header otherwise.
  442. //
  443. // Response is ignored if resp is nil.
  444. //
  445. // The function doesn't follow redirects. Use Get* for following redirects.
  446. //
  447. // ErrNoFreeConns is returned if all Client.MaxConnsPerHost connections
  448. // to the requested host are busy.
  449. //
  450. // It is recommended obtaining req and resp via AcquireRequest
  451. // and AcquireResponse in performance-critical code.
  452. func (c *Client) Do(req *Request, resp *Response) error {
  453. uri := req.URI()
  454. if uri == nil {
  455. return ErrorInvalidURI
  456. }
  457. host := uri.Host()
  458. if bytes.ContainsRune(host, ',') {
  459. return fmt.Errorf("invalid host %q. Use HostClient for multiple hosts", host)
  460. }
  461. isTLS := false
  462. if uri.isHTTPS() {
  463. isTLS = true
  464. } else if !uri.isHTTP() {
  465. return fmt.Errorf("unsupported protocol %q. http and https are supported", uri.Scheme())
  466. }
  467. c.mOnce.Do(func() {
  468. c.m = make(map[string]*HostClient)
  469. c.ms = make(map[string]*HostClient)
  470. })
  471. hc, err := c.hostClient(host, isTLS)
  472. if err != nil {
  473. return err
  474. }
  475. atomic.AddInt32(&hc.pendingClientRequests, 1)
  476. defer atomic.AddInt32(&hc.pendingClientRequests, -1)
  477. return hc.Do(req, resp)
  478. }
  479. func (c *Client) hostClient(host []byte, isTLS bool) (*HostClient, error) {
  480. m := c.m
  481. if isTLS {
  482. m = c.ms
  483. }
  484. c.mLock.RLock()
  485. hc, exist := m[string(host)]
  486. c.mLock.RUnlock()
  487. if exist {
  488. return hc, nil
  489. }
  490. c.mLock.Lock()
  491. defer c.mLock.Unlock()
  492. hc, exist = m[string(host)]
  493. if exist {
  494. return hc, nil
  495. }
  496. hc = &HostClient{
  497. Addr: AddMissingPort(string(host), isTLS),
  498. Transport: c.Transport,
  499. Name: c.Name,
  500. NoDefaultUserAgentHeader: c.NoDefaultUserAgentHeader,
  501. Dial: c.Dial,
  502. DialTimeout: c.DialTimeout,
  503. DialDualStack: c.DialDualStack,
  504. IsTLS: isTLS,
  505. TLSConfig: c.TLSConfig,
  506. MaxConns: c.MaxConnsPerHost,
  507. MaxIdleConnDuration: c.MaxIdleConnDuration,
  508. MaxConnDuration: c.MaxConnDuration,
  509. MaxIdemponentCallAttempts: c.MaxIdemponentCallAttempts,
  510. ReadBufferSize: c.ReadBufferSize,
  511. WriteBufferSize: c.WriteBufferSize,
  512. ReadTimeout: c.ReadTimeout,
  513. WriteTimeout: c.WriteTimeout,
  514. MaxResponseBodySize: c.MaxResponseBodySize,
  515. DisableHeaderNamesNormalizing: c.DisableHeaderNamesNormalizing,
  516. DisablePathNormalizing: c.DisablePathNormalizing,
  517. MaxConnWaitTimeout: c.MaxConnWaitTimeout,
  518. RetryIf: c.RetryIf,
  519. RetryIfErr: c.RetryIfErr,
  520. RetryIfErrUpstream: c.RetryIfErrUpstream,
  521. ConnPoolStrategy: c.ConnPoolStrategy,
  522. StreamResponseBody: c.StreamResponseBody,
  523. clientReaderPool: &c.readerPool,
  524. clientWriterPool: &c.writerPool,
  525. }
  526. if c.ConfigureClient != nil {
  527. if err := c.ConfigureClient(hc); err != nil {
  528. return nil, err
  529. }
  530. }
  531. m[string(host)] = hc
  532. if len(m) == 1 {
  533. go c.mCleaner(m)
  534. }
  535. return hc, nil
  536. }
  537. // CloseIdleConnections closes any connections which were previously
  538. // connected from previous requests but are now sitting idle in a
  539. // "keep-alive" state. It does not interrupt any connections currently
  540. // in use.
  541. func (c *Client) CloseIdleConnections() {
  542. c.mLock.RLock()
  543. for _, v := range c.m {
  544. v.CloseIdleConnections()
  545. }
  546. for _, v := range c.ms {
  547. v.CloseIdleConnections()
  548. }
  549. c.mLock.RUnlock()
  550. }
  551. func (c *Client) mCleaner(m map[string]*HostClient) {
  552. mustStop := false
  553. sleep := c.MaxIdleConnDuration
  554. if sleep < time.Second {
  555. sleep = time.Second
  556. } else if sleep > 10*time.Second {
  557. sleep = 10 * time.Second
  558. }
  559. for {
  560. time.Sleep(sleep)
  561. c.mLock.Lock()
  562. for k, v := range m {
  563. v.connsLock.Lock()
  564. if v.connsCount == 0 && atomic.LoadInt32(&v.pendingClientRequests) == 0 {
  565. delete(m, k)
  566. }
  567. v.connsLock.Unlock()
  568. }
  569. if len(m) == 0 {
  570. mustStop = true
  571. }
  572. c.mLock.Unlock()
  573. if mustStop {
  574. break
  575. }
  576. }
  577. }
  578. // DefaultMaxConnsPerHost is the maximum number of concurrent connections
  579. // http client may establish per host by default (i.e. if
  580. // Client.MaxConnsPerHost isn't set).
  581. const DefaultMaxConnsPerHost = 512
  582. // DefaultMaxIdleConnDuration is the default duration before idle keep-alive
  583. // connection is closed.
  584. const DefaultMaxIdleConnDuration = 10 * time.Second
  585. // DefaultMaxIdemponentCallAttempts is the default idempotent calls attempts count.
  586. const DefaultMaxIdemponentCallAttempts = 5
  587. // DialFunc must establish connection to addr.
  588. //
  589. // There is no need in establishing TLS (SSL) connection for https.
  590. // The client automatically converts connection to TLS
  591. // if HostClient.IsTLS is set.
  592. //
  593. // TCP address passed to DialFunc always contains host and port.
  594. // Example TCP addr values:
  595. //
  596. // - foobar.com:80
  597. // - foobar.com:443
  598. // - foobar.com:8080
  599. type DialFunc func(addr string) (net.Conn, error)
  600. // DialFuncWithTimeout must establish connection to addr.
  601. // Unlike DialFunc, it also accepts a timeout.
  602. //
  603. // There is no need in establishing TLS (SSL) connection for https.
  604. // The client automatically converts connection to TLS
  605. // if HostClient.IsTLS is set.
  606. //
  607. // TCP address passed to DialFuncWithTimeout always contains host and port.
  608. // Example TCP addr values:
  609. //
  610. // - foobar.com:80
  611. // - foobar.com:443
  612. // - foobar.com:8080
  613. type DialFuncWithTimeout func(addr string, timeout time.Duration) (net.Conn, error)
  614. // RetryIfFunc defines the signature of the retry if function.
  615. // Request argument passed to RetryIfFunc, if there are any request errors.
  616. type RetryIfFunc func(request *Request) bool
  617. // RetryIfErrFunc defines an interface used for implementing the following functionality:
  618. // When the client encounters an error during a request, the behavior—whether to retry
  619. // and whether to reset the request timeout—should be determined
  620. // based on the return value of this interface.
  621. //
  622. // attempt indicates which attempt the current retry is due to a failure of.
  623. // The first request counts as the first attempt.
  624. //
  625. // err represents the error encountered while attempting the `attempts`-th request.
  626. //
  627. // resetTimeout indicates whether to reuse the `Request`'s timeout as the timeout interval,
  628. // rather than using the timeout after subtracting the time spent on previous failed requests.
  629. // This return value is meaningful only when you use `Request.SetTimeout`, `DoTimeout`, or `DoDeadline`.
  630. //
  631. // retry indicates whether to retry the current request. If it is false,
  632. // the request function will immediately return with the `err`.
  633. type RetryIfErrFunc func(request *Request, attempts int, err error) (resetTimeout bool, retry bool)
  634. // RetryIfErrUpstreamFunc works just like a RetryIfErrFunc and also provides
  635. // information about which upstream caused the error, if known.
  636. //
  637. // Upstream information is a <host>:<port> format.
  638. type RetryIfErrUpstreamFunc func(request *Request, attempts int, err error, upstream string) (resetTimeout bool, retry bool)
  639. // RoundTripper wraps every request/response.
  640. type RoundTripper interface {
  641. RoundTrip(hc *HostClient, req *Request, resp *Response) (retry bool, err error)
  642. }
  643. // ConnPoolStrategyType define strategy of connection pool enqueue/dequeue.
  644. type ConnPoolStrategyType int
  645. const (
  646. FIFO ConnPoolStrategyType = iota
  647. LIFO
  648. )
  649. // HostClient balances http requests among hosts listed in Addr.
  650. //
  651. // HostClient may be used for balancing load among multiple upstream hosts.
  652. // While multiple addresses passed to HostClient.Addr may be used for balancing
  653. // load among them, it would be better using LBClient instead, since HostClient
  654. // may unevenly balance load among upstream hosts.
  655. //
  656. // It is forbidden copying HostClient instances. Create new instances instead.
  657. //
  658. // It is safe calling HostClient methods from concurrently running goroutines.
  659. type HostClient struct {
  660. noCopy noCopy
  661. readerPool sync.Pool
  662. writerPool sync.Pool
  663. // Transport defines a transport-like mechanism that wraps every request/response.
  664. Transport RoundTripper
  665. // Callback for establishing new connections to hosts.
  666. //
  667. // Default DialTimeout is used if not set.
  668. DialTimeout DialFuncWithTimeout
  669. // Callback for establishing new connections to hosts.
  670. //
  671. // Note that if Dial is set instead of DialTimeout, Dial will ignore Request timeout.
  672. // If you want the tcp dial process to account for request timeouts, use DialTimeout instead.
  673. //
  674. // If not set, DialTimeout is used.
  675. Dial DialFunc
  676. // Optional TLS config.
  677. TLSConfig *tls.Config
  678. // RetryIf controls whether a retry should be attempted after an error.
  679. // By default, it uses the isIdempotent function.
  680. //
  681. // Deprecated: Use RetryIfErr instead.
  682. // This field is only effective when the `RetryIfErr` field is not set.
  683. RetryIf RetryIfFunc
  684. // When the client encounters an error during a request, the behavior—whether to retry
  685. // and whether to reset the request timeout—should be determined
  686. // based on the return value of this field.
  687. // This field is only effective within the range of MaxIdemponentCallAttempts.
  688. RetryIfErr RetryIfErrFunc
  689. // RetryIfErrUpstream works just like RetryIfErr but also provides information about which upstream causes the error, if known.
  690. // Upstream information is a <host>:<port> format.
  691. RetryIfErrUpstream RetryIfErrUpstreamFunc
  692. connsWait *wantConnQueue
  693. tlsConfigMap map[string]*tls.Config
  694. clientReaderPool *sync.Pool
  695. clientWriterPool *sync.Pool
  696. // Comma-separated list of upstream HTTP server host addresses,
  697. // which are passed to Dial or DialTimeout in a round-robin manner.
  698. //
  699. // Each address may contain port if default dialer is used.
  700. // For example,
  701. //
  702. // - foobar.com:80
  703. // - foobar.com:443
  704. // - foobar.com:8080
  705. Addr string
  706. // Client name. Used in User-Agent request header.
  707. Name string
  708. conns []*clientConn
  709. addrs []string
  710. // Maximum number of connections which may be established to all hosts
  711. // listed in Addr.
  712. //
  713. // You can change this value while the HostClient is being used
  714. // with HostClient.SetMaxConns(value)
  715. //
  716. // DefaultMaxConnsPerHost is used if not set.
  717. MaxConns int
  718. // Keep-alive connections are closed after this duration.
  719. //
  720. // By default connection duration is unlimited.
  721. MaxConnDuration time.Duration
  722. // Idle keep-alive connections are closed after this duration.
  723. //
  724. // By default idle connections are closed
  725. // after DefaultMaxIdleConnDuration.
  726. MaxIdleConnDuration time.Duration
  727. // Maximum number of attempts for idempotent calls.
  728. //
  729. // A value of 0 or a negative value represents using DefaultMaxIdemponentCallAttempts.
  730. // For example, a value of 1 means the request will be executed only once,
  731. // while 2 means the request will be executed at most twice.
  732. // The RetryIfErr and RetryIf fields can invalidate remaining attempts.
  733. MaxIdemponentCallAttempts int
  734. // Per-connection buffer size for responses' reading.
  735. // This also limits the maximum header size.
  736. //
  737. // Default buffer size is used if 0.
  738. ReadBufferSize int
  739. // Per-connection buffer size for requests' writing.
  740. //
  741. // Default buffer size is used if 0.
  742. WriteBufferSize int
  743. // Maximum duration for full response reading (including body).
  744. //
  745. // By default response read timeout is unlimited.
  746. ReadTimeout time.Duration
  747. // Maximum duration for full request writing (including body).
  748. //
  749. // By default request write timeout is unlimited.
  750. WriteTimeout time.Duration
  751. // Maximum response body size.
  752. //
  753. // The client returns ErrBodyTooLarge if this limit is greater than 0
  754. // and response body is greater than the limit.
  755. //
  756. // By default response body size is unlimited.
  757. MaxResponseBodySize int
  758. // Maximum duration for waiting for a free connection.
  759. //
  760. // By default will not waiting, return ErrNoFreeConns immediately
  761. MaxConnWaitTimeout time.Duration
  762. // Connection pool strategy. Can be either LIFO or FIFO (default).
  763. ConnPoolStrategy ConnPoolStrategyType
  764. connsCount int
  765. connsLock sync.Mutex
  766. addrsLock sync.Mutex
  767. tlsConfigMapLock sync.Mutex
  768. addrIdx uint32
  769. lastUseTime uint32
  770. pendingRequests int32
  771. // pendingClientRequests counts the number of requests that a Client is currently running using this HostClient.
  772. // It will be incremented earlier than pendingRequests and will be used by Client to see if the HostClient is still in use.
  773. pendingClientRequests int32
  774. // NoDefaultUserAgentHeader when set to true, causes the default
  775. // User-Agent header to be excluded from the Request.
  776. NoDefaultUserAgentHeader bool
  777. // Attempt to connect to both ipv4 and ipv6 host addresses
  778. // if set to true.
  779. //
  780. // This option is used only if default TCP dialer is used,
  781. // i.e. if Dial and DialTimeout are blank.
  782. //
  783. // By default client connects only to ipv4 addresses,
  784. // since unfortunately ipv6 remains broken in many networks worldwide :)
  785. DialDualStack bool
  786. // Whether to use TLS (aka SSL or HTTPS) for host connections.
  787. IsTLS bool
  788. // Header names are passed as-is without normalization
  789. // if this option is set.
  790. //
  791. // Disabled header names' normalization may be useful only for proxying
  792. // responses to other clients expecting case-sensitive
  793. // header names. See https://github.com/valyala/fasthttp/issues/57
  794. // for details.
  795. //
  796. // By default request and response header names are normalized, i.e.
  797. // The first letter and the first letters following dashes
  798. // are uppercased, while all the other letters are lowercased.
  799. // Examples:
  800. //
  801. // * HOST -> Host
  802. // * content-type -> Content-Type
  803. // * cONTENT-lenGTH -> Content-Length
  804. DisableHeaderNamesNormalizing bool
  805. // Path values are sent as-is without normalization.
  806. //
  807. // Disabled path normalization may be useful for proxying incoming requests
  808. // to servers that are expecting paths to be forwarded as-is.
  809. //
  810. // By default path values are normalized, i.e.
  811. // extra slashes are removed, special characters are encoded.
  812. DisablePathNormalizing bool
  813. // Will not log potentially sensitive content in error logs.
  814. //
  815. // This option is useful for servers that handle sensitive data
  816. // in the request/response.
  817. //
  818. // Client logs full errors by default.
  819. SecureErrorLogMessage bool
  820. // StreamResponseBody enables response body streaming.
  821. StreamResponseBody bool
  822. connsCleanerRun bool
  823. }
  824. type clientConn struct {
  825. c net.Conn
  826. createdTime time.Time
  827. lastUseTime time.Time
  828. }
  829. // Conn returns the underlying net.Conn associated with the client connection.
  830. func (cc *clientConn) Conn() net.Conn {
  831. return cc.c
  832. }
  833. // CreatedTime returns time the client was created.
  834. func (cc *clientConn) CreatedTime() time.Time {
  835. return cc.createdTime
  836. }
  837. // LastUseTime returns time the client was last used.
  838. func (cc *clientConn) LastUseTime() time.Time {
  839. return cc.lastUseTime
  840. }
  841. var startTimeUnix = time.Now().Unix()
  842. // LastUseTime returns time the client was last used.
  843. func (c *HostClient) LastUseTime() time.Time {
  844. n := atomic.LoadUint32(&c.lastUseTime)
  845. return time.Unix(startTimeUnix+int64(n), 0)
  846. }
  847. // Get returns the status code and body of url.
  848. //
  849. // The contents of dst will be replaced by the body and returned, if the dst
  850. // is too small a new slice will be allocated.
  851. //
  852. // The function follows redirects. Use Do* for manually handling redirects.
  853. func (c *HostClient) Get(dst []byte, url string) (statusCode int, body []byte, err error) {
  854. return clientGetURL(dst, url, c)
  855. }
  856. // GetTimeout returns the status code and body of url.
  857. //
  858. // The contents of dst will be replaced by the body and returned, if the dst
  859. // is too small a new slice will be allocated.
  860. //
  861. // The function follows redirects. Use Do* for manually handling redirects.
  862. //
  863. // ErrTimeout error is returned if url contents couldn't be fetched
  864. // during the given timeout.
  865. func (c *HostClient) GetTimeout(dst []byte, url string, timeout time.Duration) (statusCode int, body []byte, err error) {
  866. return clientGetURLTimeout(dst, url, timeout, c)
  867. }
  868. // GetDeadline returns the status code and body of url.
  869. //
  870. // The contents of dst will be replaced by the body and returned, if the dst
  871. // is too small a new slice will be allocated.
  872. //
  873. // The function follows redirects. Use Do* for manually handling redirects.
  874. //
  875. // ErrTimeout error is returned if url contents couldn't be fetched
  876. // until the given deadline.
  877. func (c *HostClient) GetDeadline(dst []byte, url string, deadline time.Time) (statusCode int, body []byte, err error) {
  878. return clientGetURLDeadline(dst, url, deadline, c)
  879. }
  880. // Post sends POST request to the given url with the given POST arguments.
  881. //
  882. // The contents of dst will be replaced by the body and returned, if the dst
  883. // is too small a new slice will be allocated.
  884. //
  885. // The function follows redirects. Use Do* for manually handling redirects.
  886. //
  887. // Empty POST body is sent if postArgs is nil.
  888. func (c *HostClient) Post(dst []byte, url string, postArgs *Args) (statusCode int, body []byte, err error) {
  889. return clientPostURL(dst, url, postArgs, c)
  890. }
  891. type clientDoer interface {
  892. Do(req *Request, resp *Response) error
  893. }
  894. func clientGetURL(dst []byte, url string, c clientDoer) (statusCode int, body []byte, err error) {
  895. req := AcquireRequest()
  896. statusCode, body, err = doRequestFollowRedirectsBuffer(req, dst, url, c)
  897. ReleaseRequest(req)
  898. return statusCode, body, err
  899. }
  900. func clientGetURLTimeout(dst []byte, url string, timeout time.Duration, c clientDoer) (statusCode int, body []byte, err error) {
  901. deadline := time.Now().Add(timeout)
  902. return clientGetURLDeadline(dst, url, deadline, c)
  903. }
  904. type clientURLResponse struct {
  905. err error
  906. body []byte
  907. statusCode int
  908. }
  909. func clientGetURLDeadline(dst []byte, url string, deadline time.Time, c clientDoer) (statusCode int, body []byte, err error) {
  910. timeout := time.Until(deadline)
  911. if timeout <= 0 {
  912. return 0, dst, ErrTimeout
  913. }
  914. var ch chan clientURLResponse
  915. chv := clientURLResponseChPool.Get()
  916. if chv == nil {
  917. chv = make(chan clientURLResponse, 1)
  918. }
  919. ch = chv.(chan clientURLResponse)
  920. // Note that the request continues execution on ErrTimeout until
  921. // client-specific ReadTimeout exceeds. This helps limiting load
  922. // on slow hosts by MaxConns* concurrent requests.
  923. //
  924. // Without this 'hack' the load on slow host could exceed MaxConns*
  925. // concurrent requests, since timed out requests on client side
  926. // usually continue execution on the host.
  927. var mu sync.Mutex
  928. var timedout, responded bool
  929. go func() {
  930. req := AcquireRequest()
  931. statusCodeCopy, bodyCopy, errCopy := doRequestFollowRedirectsBuffer(req, dst, url, c)
  932. mu.Lock()
  933. if !timedout {
  934. ch <- clientURLResponse{
  935. statusCode: statusCodeCopy,
  936. body: bodyCopy,
  937. err: errCopy,
  938. }
  939. responded = true
  940. }
  941. mu.Unlock()
  942. ReleaseRequest(req)
  943. }()
  944. tc := AcquireTimer(timeout)
  945. select {
  946. case resp := <-ch:
  947. statusCode = resp.statusCode
  948. body = resp.body
  949. err = resp.err
  950. case <-tc.C:
  951. mu.Lock()
  952. if responded {
  953. resp := <-ch
  954. statusCode = resp.statusCode
  955. body = resp.body
  956. err = resp.err
  957. } else {
  958. timedout = true
  959. err = ErrTimeout
  960. body = dst
  961. }
  962. mu.Unlock()
  963. }
  964. ReleaseTimer(tc)
  965. clientURLResponseChPool.Put(chv)
  966. return statusCode, body, err
  967. }
  968. var clientURLResponseChPool sync.Pool
  969. func clientPostURL(dst []byte, url string, postArgs *Args, c clientDoer) (statusCode int, body []byte, err error) {
  970. req := AcquireRequest()
  971. defer ReleaseRequest(req)
  972. req.Header.SetMethod(MethodPost)
  973. req.Header.SetContentTypeBytes(strPostArgsContentType)
  974. if postArgs != nil {
  975. if _, err := postArgs.WriteTo(req.BodyWriter()); err != nil {
  976. return 0, nil, err
  977. }
  978. }
  979. statusCode, body, err = doRequestFollowRedirectsBuffer(req, dst, url, c)
  980. return statusCode, body, err
  981. }
  982. var (
  983. // ErrMissingLocation is returned by clients when the Location header is missing on
  984. // an HTTP response with a redirect status code.
  985. ErrMissingLocation = errors.New("missing Location header for http redirect")
  986. // ErrTooManyRedirects is returned by clients when the number of redirects followed
  987. // exceed the max count.
  988. ErrTooManyRedirects = errors.New("too many redirects detected when doing the request")
  989. // ErrHostClientRedirectToDifferentScheme is returned when a HostClient follows a redirect to a different protocol.
  990. ErrHostClientRedirectToDifferentScheme = errors.New("HostClient can't follow redirects to a different protocol," +
  991. " please use Client instead")
  992. )
  993. const defaultMaxRedirectsCount = 16
  994. func doRequestFollowRedirectsBuffer(req *Request, dst []byte, url string, c clientDoer) (statusCode int, body []byte, err error) {
  995. resp := AcquireResponse()
  996. bodyBuf := resp.bodyBuffer()
  997. resp.keepBodyBuffer = true
  998. oldBody := bodyBuf.B
  999. bodyBuf.B = dst
  1000. statusCode, _, err = doRequestFollowRedirects(req, resp, url, defaultMaxRedirectsCount, c)
  1001. body = bodyBuf.B
  1002. bodyBuf.B = oldBody
  1003. resp.keepBodyBuffer = false
  1004. ReleaseResponse(resp)
  1005. return statusCode, body, err
  1006. }
  1007. func doRequestFollowRedirects(
  1008. req *Request, resp *Response, url string, maxRedirectsCount int, c clientDoer,
  1009. ) (statusCode int, body []byte, err error) {
  1010. redirectsCount := 0
  1011. initialHost := hostnameFromURLString(url)
  1012. for {
  1013. req.SetRequestURI(url)
  1014. if err := req.parseURI(); err != nil {
  1015. return 0, nil, err
  1016. }
  1017. if err = c.Do(req, resp); err != nil {
  1018. break
  1019. }
  1020. statusCode = resp.Header.StatusCode()
  1021. if !StatusCodeIsRedirect(statusCode) {
  1022. break
  1023. }
  1024. redirectsCount++
  1025. if redirectsCount > maxRedirectsCount {
  1026. err = ErrTooManyRedirects
  1027. break
  1028. }
  1029. location := resp.Header.peek(strLocation)
  1030. if len(location) == 0 {
  1031. err = ErrMissingLocation
  1032. break
  1033. }
  1034. redirectURI := AcquireURI()
  1035. url = getRedirectURL(url, location, req.DisableRedirectPathNormalizing, redirectURI)
  1036. stripSensitiveHeadersOnRedirect(req, initialHost, redirectURI)
  1037. ReleaseURI(redirectURI)
  1038. if string(req.Header.Method()) == "POST" && (statusCode == 301 || statusCode == 302) {
  1039. req.Header.SetMethod(MethodGet)
  1040. }
  1041. }
  1042. return statusCode, body, err
  1043. }
  1044. func getRedirectURL(baseURL string, location []byte, disablePathNormalizing bool, dst *URI) string {
  1045. dst.Update(baseURL)
  1046. dst.UpdateBytes(location)
  1047. dst.DisablePathNormalizing = disablePathNormalizing
  1048. return dst.String()
  1049. }
  1050. // Redirect handling reuses the original Request, so sensitive request
  1051. // headers must be cleared before following redirects that net/http treats
  1052. // as untrusted.
  1053. func stripSensitiveHeadersOnRedirect(req *Request, initialHost []byte, redirectURI *URI) {
  1054. if !shouldStripSensitiveHeadersOnRedirect(initialHost, redirectURI.Host()) {
  1055. return
  1056. }
  1057. req.Header.Del(HeaderAuthorization)
  1058. req.Header.Del(HeaderCookie)
  1059. req.Header.Del(HeaderCookie2) // Match net/http behavior.
  1060. req.Header.Del(HeaderProxyAuthenticate)
  1061. req.Header.Del(HeaderProxyAuthorization)
  1062. req.Header.Del(HeaderWWWAuthenticate)
  1063. }
  1064. // shouldStripSensitiveHeadersOnRedirect defines the trust boundary for
  1065. // caller-supplied credentials during redirect handling.
  1066. //
  1067. // net/http forwards sensitive headers only to trusted redirect targets and
  1068. // documents that policy in the Client redirect handling:
  1069. // https://github.com/golang/go/blob/go1.24.1/src/net/http/client.go#L41-L49
  1070. // https://github.com/golang/go/blob/go1.24.1/src/net/http/client.go#L1005-L1021
  1071. //
  1072. // Match that behavior here by anchoring the trust decision to the initial
  1073. // request host, ignoring ports and scheme, and allowing exact-host or
  1074. // subdomain redirects to keep caller-supplied credentials.
  1075. func shouldStripSensitiveHeadersOnRedirect(initialHost, redirectHostPort []byte) bool {
  1076. return !isDomainOrSubdomainBytes(hostnameFromHostPortBytes(redirectHostPort), initialHost)
  1077. }
  1078. func hostnameFromURLString(url string) []byte {
  1079. _, host, _ := splitHostURI(nil, s2b(url))
  1080. if n := bytes.LastIndexByte(host, '@'); n >= 0 {
  1081. host = host[n+1:]
  1082. }
  1083. return hostnameFromHostPortBytes(host)
  1084. }
  1085. func hostnameFromHostPortBytes(hostPort []byte) []byte {
  1086. host, _ := splitHostPortBytes(hostPort)
  1087. if len(host) >= 2 && host[0] == '[' && host[len(host)-1] == ']' {
  1088. return host[1 : len(host)-1]
  1089. }
  1090. return host
  1091. }
  1092. func isDomainOrSubdomainBytes(sub, parent []byte) bool {
  1093. if bytes.EqualFold(sub, parent) {
  1094. return true
  1095. }
  1096. if len(sub) <= len(parent) || bytes.IndexByte(sub, ':') >= 0 || bytes.IndexByte(sub, '%') >= 0 {
  1097. return false
  1098. }
  1099. if !bytes.EqualFold(sub[len(sub)-len(parent):], parent) {
  1100. return false
  1101. }
  1102. return sub[len(sub)-len(parent)-1] == '.'
  1103. }
  1104. func splitHostPortBytes(hostPort []byte) ([]byte, []byte) {
  1105. if len(hostPort) == 0 {
  1106. return hostPort, nil
  1107. }
  1108. if hostPort[0] == '[' {
  1109. n := bytes.LastIndexByte(hostPort, ']')
  1110. if n >= 0 && n+1 < len(hostPort) && hostPort[n+1] == ':' {
  1111. return hostPort[:n+1], hostPort[n+2:]
  1112. }
  1113. return hostPort, nil
  1114. }
  1115. n := bytes.LastIndexByte(hostPort, ':')
  1116. if n < 0 || bytes.IndexByte(hostPort[:n], ':') >= 0 {
  1117. return hostPort, nil
  1118. }
  1119. return hostPort[:n], hostPort[n+1:]
  1120. }
  1121. // StatusCodeIsRedirect returns true if the status code indicates a redirect.
  1122. func StatusCodeIsRedirect(statusCode int) bool {
  1123. return statusCode == StatusMovedPermanently ||
  1124. statusCode == StatusFound ||
  1125. statusCode == StatusSeeOther ||
  1126. statusCode == StatusTemporaryRedirect ||
  1127. statusCode == StatusPermanentRedirect
  1128. }
  1129. var (
  1130. requestPool sync.Pool
  1131. responsePool sync.Pool
  1132. )
  1133. // AcquireRequest returns an empty Request instance from request pool.
  1134. //
  1135. // The returned Request instance may be passed to ReleaseRequest when it is
  1136. // no longer needed. This allows Request recycling, reduces GC pressure
  1137. // and usually improves performance.
  1138. func AcquireRequest() *Request {
  1139. v := requestPool.Get()
  1140. if v == nil {
  1141. return &Request{}
  1142. }
  1143. return v.(*Request)
  1144. }
  1145. // ReleaseRequest returns req acquired via AcquireRequest to request pool.
  1146. //
  1147. // It is forbidden accessing req and/or its' members after returning
  1148. // it to request pool.
  1149. func ReleaseRequest(req *Request) {
  1150. req.Reset()
  1151. requestPool.Put(req)
  1152. }
  1153. // AcquireResponse returns an empty Response instance from response pool.
  1154. //
  1155. // The returned Response instance may be passed to ReleaseResponse when it is
  1156. // no longer needed. This allows Response recycling, reduces GC pressure
  1157. // and usually improves performance.
  1158. func AcquireResponse() *Response {
  1159. v := responsePool.Get()
  1160. if v == nil {
  1161. return &Response{}
  1162. }
  1163. return v.(*Response)
  1164. }
  1165. // ReleaseResponse return resp acquired via AcquireResponse to response pool.
  1166. //
  1167. // It is forbidden accessing resp and/or its' members after returning
  1168. // it to response pool.
  1169. func ReleaseResponse(resp *Response) {
  1170. resp.Reset()
  1171. responsePool.Put(resp)
  1172. }
  1173. // DoTimeout performs the given request and waits for response during
  1174. // the given timeout duration.
  1175. //
  1176. // Request must contain at least non-zero RequestURI with full url (including
  1177. // scheme and host) or non-zero Host header + RequestURI.
  1178. //
  1179. // The function doesn't follow redirects. Use Get* for following redirects.
  1180. //
  1181. // Response is ignored if resp is nil.
  1182. //
  1183. // ErrTimeout is returned if the response wasn't returned during
  1184. // the given timeout.
  1185. // Immediately returns ErrTimeout if timeout value is negative.
  1186. //
  1187. // ErrNoFreeConns is returned if all HostClient.MaxConns connections
  1188. // to the host are busy.
  1189. //
  1190. // It is recommended obtaining req and resp via AcquireRequest
  1191. // and AcquireResponse in performance-critical code.
  1192. func (c *HostClient) DoTimeout(req *Request, resp *Response, timeout time.Duration) error {
  1193. req.timeout = timeout
  1194. if req.timeout <= 0 {
  1195. return ErrTimeout
  1196. }
  1197. return c.Do(req, resp)
  1198. }
  1199. // DoDeadline performs the given request and waits for response until
  1200. // the given deadline.
  1201. //
  1202. // Request must contain at least non-zero RequestURI with full url (including
  1203. // scheme and host) or non-zero Host header + RequestURI.
  1204. //
  1205. // The function doesn't follow redirects. Use Get* for following redirects.
  1206. //
  1207. // Response is ignored if resp is nil.
  1208. //
  1209. // ErrTimeout is returned if the response wasn't returned until
  1210. // the given deadline.
  1211. // Immediately returns ErrTimeout if the deadline has already been reached.
  1212. //
  1213. // ErrNoFreeConns is returned if all HostClient.MaxConns connections
  1214. // to the host are busy.
  1215. //
  1216. // It is recommended obtaining req and resp via AcquireRequest
  1217. // and AcquireResponse in performance-critical code.
  1218. func (c *HostClient) DoDeadline(req *Request, resp *Response, deadline time.Time) error {
  1219. req.timeout = time.Until(deadline)
  1220. if req.timeout <= 0 {
  1221. return ErrTimeout
  1222. }
  1223. return c.Do(req, resp)
  1224. }
  1225. // DoRedirects performs the given http request and fills the given http response,
  1226. // following up to maxRedirectsCount redirects. When the redirect count exceeds
  1227. // maxRedirectsCount, ErrTooManyRedirects is returned.
  1228. //
  1229. // Request must contain at least non-zero RequestURI with full url (including
  1230. // scheme and host) or non-zero Host header + RequestURI.
  1231. //
  1232. // Client determines the server to be requested in the following order:
  1233. //
  1234. // - from RequestURI if it contains full url with scheme and host;
  1235. // - from Host header otherwise.
  1236. //
  1237. // Response is ignored if resp is nil.
  1238. //
  1239. // ErrNoFreeConns is returned if all DefaultMaxConnsPerHost connections
  1240. // to the requested host are busy.
  1241. //
  1242. // It is recommended obtaining req and resp via AcquireRequest
  1243. // and AcquireResponse in performance-critical code.
  1244. func (c *HostClient) DoRedirects(req *Request, resp *Response, maxRedirectsCount int) error {
  1245. if c.DisablePathNormalizing {
  1246. req.URI().DisablePathNormalizing = true
  1247. }
  1248. _, _, err := doRequestFollowRedirects(req, resp, req.URI().String(), maxRedirectsCount, c)
  1249. return err
  1250. }
  1251. // Do performs the given http request and sets the corresponding response.
  1252. //
  1253. // Request must contain at least non-zero RequestURI with full url (including
  1254. // scheme and host) or non-zero Host header + RequestURI.
  1255. //
  1256. // The function doesn't follow redirects. Use Get* for following redirects.
  1257. //
  1258. // Response is ignored if resp is nil.
  1259. //
  1260. // ErrNoFreeConns is returned if all HostClient.MaxConns connections
  1261. // to the host are busy.
  1262. //
  1263. // It is recommended obtaining req and resp via AcquireRequest
  1264. // and AcquireResponse in performance-critical code.
  1265. func (c *HostClient) Do(req *Request, resp *Response) error {
  1266. var (
  1267. err error
  1268. retry bool
  1269. resetTimeout bool
  1270. )
  1271. maxAttempts := c.MaxIdemponentCallAttempts
  1272. if maxAttempts <= 0 {
  1273. maxAttempts = DefaultMaxIdemponentCallAttempts
  1274. }
  1275. attempts := 0
  1276. hasBodyStream := req.IsBodyStream()
  1277. // If a request has a timeout we store the timeout
  1278. // and calculate a deadline so we can keep updating the
  1279. // timeout on each retry.
  1280. deadline := time.Time{}
  1281. timeout := req.timeout
  1282. if timeout > 0 {
  1283. deadline = time.Now().Add(timeout)
  1284. }
  1285. retryFunc := c.RetryIf
  1286. if retryFunc == nil {
  1287. retryFunc = isIdempotent
  1288. }
  1289. atomic.AddInt32(&c.pendingRequests, 1)
  1290. for {
  1291. // If the original timeout was set, we need to update
  1292. // the one set on the request to reflect the remaining time.
  1293. if timeout > 0 {
  1294. req.timeout = time.Until(deadline)
  1295. if req.timeout <= 0 {
  1296. err = ErrTimeout
  1297. break
  1298. }
  1299. }
  1300. retry, err = c.do(req, resp)
  1301. if err == nil || !retry {
  1302. break
  1303. }
  1304. if hasBodyStream {
  1305. break
  1306. }
  1307. // Path prioritization based on ease of computation
  1308. attempts++
  1309. if attempts >= maxAttempts {
  1310. break
  1311. }
  1312. switch {
  1313. case c.RetryIfErrUpstream != nil:
  1314. upstream := ""
  1315. if resp.RemoteAddr() != nil {
  1316. upstream = resp.RemoteAddr().String()
  1317. }
  1318. resetTimeout, retry = c.RetryIfErrUpstream(req, attempts, err, upstream)
  1319. case c.RetryIfErr != nil:
  1320. resetTimeout, retry = c.RetryIfErr(req, attempts, err)
  1321. default:
  1322. retry = retryFunc(req)
  1323. }
  1324. if !retry {
  1325. break
  1326. }
  1327. if timeout > 0 && resetTimeout {
  1328. deadline = time.Now().Add(timeout)
  1329. }
  1330. }
  1331. atomic.AddInt32(&c.pendingRequests, -1)
  1332. // Restore the original timeout.
  1333. req.timeout = timeout
  1334. if err == io.EOF {
  1335. err = ErrConnectionClosed
  1336. }
  1337. return err
  1338. }
  1339. // PendingRequests returns the current number of requests the client
  1340. // is executing.
  1341. //
  1342. // This function may be used for balancing load among multiple HostClient
  1343. // instances.
  1344. func (c *HostClient) PendingRequests() int {
  1345. return int(atomic.LoadInt32(&c.pendingRequests))
  1346. }
  1347. func isIdempotent(req *Request) bool {
  1348. return req.Header.IsGet() || req.Header.IsHead() || req.Header.IsPut()
  1349. }
  1350. func (c *HostClient) do(req *Request, resp *Response) (bool, error) {
  1351. if resp == nil {
  1352. resp = AcquireResponse()
  1353. defer ReleaseResponse(resp)
  1354. }
  1355. return c.doNonNilReqResp(req, resp)
  1356. }
  1357. func (c *HostClient) doNonNilReqResp(req *Request, resp *Response) (bool, error) {
  1358. if req == nil {
  1359. // for debugging purposes
  1360. panic("BUG: req cannot be nil")
  1361. }
  1362. if resp == nil {
  1363. // for debugging purposes
  1364. panic("BUG: resp cannot be nil")
  1365. }
  1366. // Secure header error logs configuration
  1367. resp.secureErrorLogMessage = c.SecureErrorLogMessage
  1368. resp.Header.secureErrorLogMessage = c.SecureErrorLogMessage
  1369. req.secureErrorLogMessage = c.SecureErrorLogMessage
  1370. req.Header.secureErrorLogMessage = c.SecureErrorLogMessage
  1371. if c.IsTLS != req.URI().isHTTPS() {
  1372. return false, ErrHostClientRedirectToDifferentScheme
  1373. }
  1374. atomic.StoreUint32(&c.lastUseTime, uint32(time.Now().Unix()-startTimeUnix)) // #nosec G115
  1375. // Free up resources occupied by response before sending the request,
  1376. // so the GC may reclaim these resources (e.g. response body).
  1377. // backing up SkipBody in case it was set explicitly
  1378. customSkipBody := resp.SkipBody
  1379. customStreamBody := resp.StreamBody || c.StreamResponseBody
  1380. resp.Reset()
  1381. resp.SkipBody = customSkipBody
  1382. resp.StreamBody = customStreamBody
  1383. req.URI().DisablePathNormalizing = c.DisablePathNormalizing
  1384. userAgentOld := req.Header.UserAgent()
  1385. if len(userAgentOld) == 0 {
  1386. userAgent := c.Name
  1387. if userAgent == "" && !c.NoDefaultUserAgentHeader {
  1388. userAgent = defaultUserAgent
  1389. }
  1390. if userAgent != "" {
  1391. req.Header.userAgent = append(req.Header.userAgent[:0], userAgent...)
  1392. }
  1393. }
  1394. return c.transport().RoundTrip(c, req, resp)
  1395. }
  1396. func (c *HostClient) transport() RoundTripper {
  1397. if c.Transport == nil {
  1398. return DefaultTransport
  1399. }
  1400. return c.Transport
  1401. }
  1402. var (
  1403. // ErrNoFreeConns is returned when no free connections available
  1404. // to the given host.
  1405. //
  1406. // Increase the allowed number of connections per host if you
  1407. // see this error.
  1408. ErrNoFreeConns = errors.New("no free connections available to host")
  1409. // ErrConnectionClosed may be returned from client methods if the server
  1410. // closes connection before returning the first response byte.
  1411. //
  1412. // If you see this error, then either fix the server by returning
  1413. // 'Connection: close' response header before closing the connection
  1414. // or add 'Connection: close' request header before sending requests
  1415. // to broken server.
  1416. ErrConnectionClosed = errors.New("the server closed connection before returning the first response byte. " +
  1417. "Make sure the server returns 'Connection: close' response header before closing the connection")
  1418. // ErrConnPoolStrategyNotImpl is returned when HostClient.ConnPoolStrategy is not implement yet.
  1419. // If you see this error, then you need to check your HostClient configuration.
  1420. ErrConnPoolStrategyNotImpl = errors.New("connection pool strategy is not implement")
  1421. )
  1422. type timeoutError struct{}
  1423. func (e *timeoutError) Error() string {
  1424. return "timeout"
  1425. }
  1426. // Timeout implements the Timeout behavior of the net.Error interface.
  1427. // This allows for checks like:
  1428. //
  1429. // if x, ok := err.(interface{ Timeout() bool }); ok && x.Timeout() {
  1430. func (e *timeoutError) Timeout() bool {
  1431. return true
  1432. }
  1433. // ErrTimeout is returned from timed out calls.
  1434. var ErrTimeout = &timeoutError{}
  1435. // SetMaxConns sets up the maximum number of connections which may be established to all hosts listed in Addr.
  1436. func (c *HostClient) SetMaxConns(newMaxConns int) {
  1437. c.connsLock.Lock()
  1438. c.MaxConns = newMaxConns
  1439. c.connsLock.Unlock()
  1440. }
  1441. func (c *HostClient) AcquireConn(reqTimeout time.Duration, connectionClose bool) (cc *clientConn, err error) {
  1442. createConn := false
  1443. startCleaner := false
  1444. var n int
  1445. c.connsLock.Lock()
  1446. n = len(c.conns)
  1447. if n == 0 {
  1448. maxConns := c.MaxConns
  1449. if maxConns <= 0 {
  1450. maxConns = DefaultMaxConnsPerHost
  1451. }
  1452. if c.connsCount < maxConns {
  1453. c.connsCount++
  1454. createConn = true
  1455. if !c.connsCleanerRun && !connectionClose {
  1456. startCleaner = true
  1457. c.connsCleanerRun = true
  1458. }
  1459. }
  1460. } else {
  1461. switch c.ConnPoolStrategy {
  1462. case LIFO:
  1463. n--
  1464. cc = c.conns[n]
  1465. c.conns[n] = nil
  1466. c.conns = c.conns[:n]
  1467. case FIFO:
  1468. cc = c.conns[0]
  1469. copy(c.conns, c.conns[1:])
  1470. c.conns[n-1] = nil
  1471. c.conns = c.conns[:n-1]
  1472. default:
  1473. c.connsLock.Unlock()
  1474. return nil, ErrConnPoolStrategyNotImpl
  1475. }
  1476. }
  1477. c.connsLock.Unlock()
  1478. if cc != nil {
  1479. return cc, nil
  1480. }
  1481. if !createConn {
  1482. if c.MaxConnWaitTimeout <= 0 {
  1483. return nil, ErrNoFreeConns
  1484. }
  1485. //nolint:dupword
  1486. // reqTimeout c.MaxConnWaitTimeout wait duration
  1487. // d1 d2 min(d1, d2)
  1488. // 0(not set) d2 d2
  1489. // d1 0(don't wait) 0(don't wait)
  1490. // 0(not set) d2 d2
  1491. timeout := c.MaxConnWaitTimeout
  1492. timeoutOverridden := false
  1493. // reqTimeout == 0 means not set
  1494. if reqTimeout > 0 && reqTimeout < timeout {
  1495. timeout = reqTimeout
  1496. timeoutOverridden = true
  1497. }
  1498. // wait for a free connection
  1499. tc := AcquireTimer(timeout)
  1500. defer ReleaseTimer(tc)
  1501. w := &wantConn{
  1502. ready: make(chan struct{}, 1),
  1503. }
  1504. defer func() {
  1505. if err != nil {
  1506. w.cancel(c, err)
  1507. }
  1508. }()
  1509. c.queueForIdle(w)
  1510. select {
  1511. case <-w.ready:
  1512. return w.conn, w.err
  1513. case <-tc.C:
  1514. c.connsWait.failedWaiters.Add(1)
  1515. if timeoutOverridden {
  1516. return nil, ErrTimeout
  1517. }
  1518. return nil, ErrNoFreeConns
  1519. }
  1520. }
  1521. if startCleaner {
  1522. go c.connsCleaner()
  1523. }
  1524. conn, err := c.dialHostHard(reqTimeout)
  1525. if err != nil {
  1526. c.decConnsCount()
  1527. return nil, err
  1528. }
  1529. cc = acquireClientConn(conn)
  1530. return cc, nil
  1531. }
  1532. func (c *HostClient) queueForIdle(w *wantConn) {
  1533. c.connsLock.Lock()
  1534. defer c.connsLock.Unlock()
  1535. if c.connsWait == nil {
  1536. c.connsWait = &wantConnQueue{}
  1537. }
  1538. c.connsWait.clearFront()
  1539. c.connsWait.pushBack(w)
  1540. }
  1541. func (c *HostClient) dialConnFor(w *wantConn) {
  1542. conn, err := c.dialHostHard(0)
  1543. if err != nil {
  1544. w.tryDeliver(nil, err)
  1545. c.decConnsCount()
  1546. return
  1547. }
  1548. cc := acquireClientConn(conn)
  1549. if !w.tryDeliver(cc, nil) {
  1550. // not delivered, return idle connection
  1551. c.ReleaseConn(cc)
  1552. }
  1553. }
  1554. // CloseIdleConnections closes any connections which were previously
  1555. // connected from previous requests but are now sitting idle in a
  1556. // "keep-alive" state. It does not interrupt any connections currently
  1557. // in use.
  1558. func (c *HostClient) CloseIdleConnections() {
  1559. c.connsLock.Lock()
  1560. scratch := append([]*clientConn{}, c.conns...)
  1561. for i := range c.conns {
  1562. c.conns[i] = nil
  1563. }
  1564. c.conns = c.conns[:0]
  1565. c.connsLock.Unlock()
  1566. for _, cc := range scratch {
  1567. c.CloseConn(cc)
  1568. }
  1569. }
  1570. func (c *HostClient) connsCleaner() {
  1571. var (
  1572. scratch []*clientConn
  1573. maxIdleConnDuration = c.MaxIdleConnDuration
  1574. )
  1575. if maxIdleConnDuration <= 0 {
  1576. maxIdleConnDuration = DefaultMaxIdleConnDuration
  1577. }
  1578. for {
  1579. currentTime := time.Now()
  1580. // Determine idle connections to be closed.
  1581. c.connsLock.Lock()
  1582. conns := c.conns
  1583. n := len(conns)
  1584. i := 0
  1585. for i < n && currentTime.Sub(conns[i].lastUseTime) > maxIdleConnDuration {
  1586. i++
  1587. }
  1588. sleepFor := maxIdleConnDuration
  1589. if i < n {
  1590. // + 1 so we actually sleep past the expiration time and not up to it.
  1591. // Otherwise the > check above would still fail.
  1592. sleepFor = maxIdleConnDuration - currentTime.Sub(conns[i].lastUseTime) + 1
  1593. }
  1594. scratch = append(scratch[:0], conns[:i]...)
  1595. if i > 0 {
  1596. m := copy(conns, conns[i:])
  1597. for i = m; i < n; i++ {
  1598. conns[i] = nil
  1599. }
  1600. c.conns = conns[:m]
  1601. }
  1602. c.connsLock.Unlock()
  1603. // Close idle connections.
  1604. for i, cc := range scratch {
  1605. c.CloseConn(cc)
  1606. scratch[i] = nil
  1607. }
  1608. // Determine whether to stop the connsCleaner.
  1609. c.connsLock.Lock()
  1610. mustStop := c.connsCount == 0
  1611. if mustStop {
  1612. c.connsCleanerRun = false
  1613. }
  1614. c.connsLock.Unlock()
  1615. if mustStop {
  1616. break
  1617. }
  1618. time.Sleep(sleepFor)
  1619. }
  1620. }
  1621. func (c *HostClient) CloseConn(cc *clientConn) {
  1622. c.decConnsCount()
  1623. cc.c.Close()
  1624. releaseClientConn(cc)
  1625. }
  1626. func (c *HostClient) decConnsCount() {
  1627. if c.MaxConnWaitTimeout <= 0 {
  1628. c.connsLock.Lock()
  1629. c.connsCount--
  1630. c.connsLock.Unlock()
  1631. return
  1632. }
  1633. c.connsLock.Lock()
  1634. defer c.connsLock.Unlock()
  1635. dialed := false
  1636. if q := c.connsWait; q != nil && q.len() > 0 {
  1637. for q.len() > 0 {
  1638. w := q.popFront()
  1639. if w.waiting() {
  1640. go c.dialConnFor(w)
  1641. dialed = true
  1642. break
  1643. }
  1644. c.connsWait.failedWaiters.Add(-1)
  1645. }
  1646. }
  1647. if !dialed {
  1648. c.connsCount--
  1649. }
  1650. }
  1651. // ConnsCount returns connection count of HostClient.
  1652. func (c *HostClient) ConnsCount() int {
  1653. c.connsLock.Lock()
  1654. defer c.connsLock.Unlock()
  1655. return c.connsCount
  1656. }
  1657. func acquireClientConn(conn net.Conn) *clientConn {
  1658. v := clientConnPool.Get()
  1659. if v == nil {
  1660. v = &clientConn{}
  1661. }
  1662. cc := v.(*clientConn)
  1663. cc.c = conn
  1664. cc.createdTime = time.Now()
  1665. return cc
  1666. }
  1667. func releaseClientConn(cc *clientConn) {
  1668. // Reset all fields.
  1669. *cc = clientConn{}
  1670. clientConnPool.Put(cc)
  1671. }
  1672. var clientConnPool sync.Pool
  1673. func (c *HostClient) ReleaseConn(cc *clientConn) {
  1674. cc.lastUseTime = time.Now()
  1675. if c.MaxConnWaitTimeout <= 0 {
  1676. c.connsLock.Lock()
  1677. c.conns = append(c.conns, cc)
  1678. c.connsLock.Unlock()
  1679. return
  1680. }
  1681. // try to deliver an idle connection to a *wantConn
  1682. c.connsLock.Lock()
  1683. defer c.connsLock.Unlock()
  1684. delivered := false
  1685. if q := c.connsWait; q != nil && q.len() > 0 {
  1686. for q.len() > 0 {
  1687. w := q.popFront()
  1688. if w.waiting() {
  1689. delivered = w.tryDeliver(cc, nil)
  1690. // This is the last resort to hand over conCount sema.
  1691. // We must ensure that there are no valid waiters in connsWait
  1692. // when we exit this loop.
  1693. //
  1694. // We did not apply the same looping pattern in the decConnsCount
  1695. // method because it needs to create a new time-spent connection,
  1696. // and the decConnsCount call chain will inevitably reach this point.
  1697. // When MaxConnWaitTimeout>0.
  1698. if delivered {
  1699. break
  1700. }
  1701. }
  1702. c.connsWait.failedWaiters.Add(-1)
  1703. }
  1704. }
  1705. if !delivered {
  1706. c.conns = append(c.conns, cc)
  1707. }
  1708. }
  1709. func (c *HostClient) AcquireWriter(conn net.Conn) *bufio.Writer {
  1710. var v any
  1711. if c.clientWriterPool != nil {
  1712. v = c.clientWriterPool.Get()
  1713. } else {
  1714. v = c.writerPool.Get()
  1715. }
  1716. if v == nil {
  1717. n := c.WriteBufferSize
  1718. if n <= 0 {
  1719. n = defaultWriteBufferSize
  1720. }
  1721. return bufio.NewWriterSize(conn, n)
  1722. }
  1723. bw := v.(*bufio.Writer)
  1724. bw.Reset(conn)
  1725. return bw
  1726. }
  1727. func (c *HostClient) ReleaseWriter(bw *bufio.Writer) {
  1728. if c.clientWriterPool != nil {
  1729. c.clientWriterPool.Put(bw)
  1730. } else {
  1731. c.writerPool.Put(bw)
  1732. }
  1733. }
  1734. func (c *HostClient) AcquireReader(conn net.Conn) *bufio.Reader {
  1735. var v any
  1736. if c.clientReaderPool != nil {
  1737. v = c.clientReaderPool.Get()
  1738. } else {
  1739. v = c.readerPool.Get()
  1740. }
  1741. if v == nil {
  1742. n := c.ReadBufferSize
  1743. if n <= 0 {
  1744. n = defaultReadBufferSize
  1745. }
  1746. return bufio.NewReaderSize(conn, n)
  1747. }
  1748. br := v.(*bufio.Reader)
  1749. br.Reset(conn)
  1750. return br
  1751. }
  1752. func (c *HostClient) ReleaseReader(br *bufio.Reader) {
  1753. if c.clientReaderPool != nil {
  1754. c.clientReaderPool.Put(br)
  1755. } else {
  1756. c.readerPool.Put(br)
  1757. }
  1758. }
  1759. func newClientTLSConfig(c *tls.Config, addr string) *tls.Config {
  1760. if c == nil {
  1761. c = &tls.Config{}
  1762. } else {
  1763. c = c.Clone()
  1764. }
  1765. if c.ServerName == "" {
  1766. serverName := tlsServerName(addr)
  1767. if serverName == "*" {
  1768. c.InsecureSkipVerify = true
  1769. } else {
  1770. c.ServerName = serverName
  1771. }
  1772. }
  1773. return c
  1774. }
  1775. func tlsServerName(addr string) string {
  1776. if !strings.Contains(addr, ":") {
  1777. return addr
  1778. }
  1779. host, _, err := net.SplitHostPort(addr)
  1780. if err != nil {
  1781. return "*"
  1782. }
  1783. return host
  1784. }
  1785. func (c *HostClient) nextAddr() string {
  1786. c.addrsLock.Lock()
  1787. if c.addrs == nil {
  1788. c.addrs = strings.Split(c.Addr, ",")
  1789. }
  1790. addr := c.addrs[0]
  1791. if len(c.addrs) > 1 {
  1792. addr = c.addrs[c.addrIdx%uint32(len(c.addrs))] // #nosec G115
  1793. c.addrIdx++
  1794. }
  1795. c.addrsLock.Unlock()
  1796. return addr
  1797. }
  1798. func (c *HostClient) dialHostHard(dialTimeout time.Duration) (conn net.Conn, err error) {
  1799. // use dialTimeout to control the timeout of each dial. It does not work if dialTimeout is 0 or if
  1800. // c.DialTimeout has not been set and c.Dial has been set.
  1801. // attempt to dial all the available hosts before giving up.
  1802. c.addrsLock.Lock()
  1803. n := len(c.addrs)
  1804. c.addrsLock.Unlock()
  1805. if n == 0 {
  1806. // It looks like c.addrs isn't initialized yet.
  1807. n = 1
  1808. }
  1809. timeout := c.ReadTimeout + c.WriteTimeout
  1810. if timeout <= 0 {
  1811. timeout = DefaultDialTimeout
  1812. }
  1813. deadline := time.Now().Add(timeout)
  1814. for n > 0 {
  1815. addr := c.nextAddr()
  1816. tlsConfig := c.cachedTLSConfig(addr)
  1817. conn, err = dialAddr(addr, c.Dial, c.DialTimeout, c.DialDualStack, c.IsTLS, tlsConfig, dialTimeout, c.WriteTimeout)
  1818. if err == nil {
  1819. return conn, nil
  1820. }
  1821. if time.Since(deadline) >= 0 {
  1822. break
  1823. }
  1824. n--
  1825. }
  1826. return nil, err
  1827. }
  1828. func (c *HostClient) cachedTLSConfig(addr string) *tls.Config {
  1829. if !c.IsTLS {
  1830. return nil
  1831. }
  1832. c.tlsConfigMapLock.Lock()
  1833. if c.tlsConfigMap == nil {
  1834. c.tlsConfigMap = make(map[string]*tls.Config)
  1835. }
  1836. cfg := c.tlsConfigMap[addr]
  1837. if cfg == nil {
  1838. cfg = newClientTLSConfig(c.TLSConfig, addr)
  1839. c.tlsConfigMap[addr] = cfg
  1840. }
  1841. c.tlsConfigMapLock.Unlock()
  1842. return cfg
  1843. }
  1844. // ErrTLSHandshakeTimeout indicates there is a timeout from tls handshake.
  1845. var ErrTLSHandshakeTimeout = errors.New("tls handshake timed out")
  1846. func tlsClientHandshake(rawConn net.Conn, tlsConfig *tls.Config, deadline time.Time) (_ net.Conn, retErr error) {
  1847. defer func() {
  1848. if retErr != nil {
  1849. rawConn.Close()
  1850. }
  1851. }()
  1852. conn := tls.Client(rawConn, tlsConfig)
  1853. err := conn.SetDeadline(deadline)
  1854. if err != nil {
  1855. return nil, err
  1856. }
  1857. err = conn.Handshake()
  1858. if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
  1859. return nil, ErrTLSHandshakeTimeout
  1860. }
  1861. if err != nil {
  1862. return nil, err
  1863. }
  1864. err = conn.SetDeadline(time.Time{})
  1865. if err != nil {
  1866. return nil, err
  1867. }
  1868. return conn, nil
  1869. }
  1870. func dialAddr(
  1871. addr string, dial DialFunc, dialWithTimeout DialFuncWithTimeout, dialDualStack, isTLS bool,
  1872. tlsConfig *tls.Config, dialTimeout, writeTimeout time.Duration,
  1873. ) (net.Conn, error) {
  1874. deadline := time.Now().Add(writeTimeout)
  1875. conn, err := callDialFunc(addr, dial, dialWithTimeout, dialDualStack, isTLS, dialTimeout)
  1876. if err != nil {
  1877. return nil, err
  1878. }
  1879. if conn == nil {
  1880. return nil, errors.New("dialling unsuccessful. Please report this bug")
  1881. }
  1882. // We assume that any conn that has the Handshake() method is a TLS conn already.
  1883. // This doesn't cover just tls.Conn but also other TLS implementations.
  1884. _, isTLSAlready := conn.(interface{ Handshake() error })
  1885. if isTLS && !isTLSAlready {
  1886. if writeTimeout == 0 {
  1887. return tls.Client(conn, tlsConfig), nil
  1888. }
  1889. return tlsClientHandshake(conn, tlsConfig, deadline)
  1890. }
  1891. return conn, nil
  1892. }
  1893. func callDialFunc(
  1894. addr string, dial DialFunc, dialWithTimeout DialFuncWithTimeout, dialDualStack, isTLS bool, timeout time.Duration,
  1895. ) (net.Conn, error) {
  1896. if dialWithTimeout != nil {
  1897. return dialWithTimeout(addr, timeout)
  1898. }
  1899. if dial != nil {
  1900. return dial(addr)
  1901. }
  1902. addr = AddMissingPort(addr, isTLS)
  1903. if timeout > 0 {
  1904. if dialDualStack {
  1905. return DialDualStackTimeout(addr, timeout)
  1906. }
  1907. return DialTimeout(addr, timeout)
  1908. }
  1909. if dialDualStack {
  1910. return DialDualStack(addr)
  1911. }
  1912. return Dial(addr)
  1913. }
  1914. // AddMissingPort adds a port to a host if it is missing.
  1915. // A literal IPv6 address in hostport must be enclosed in square
  1916. // brackets, as in "[::1]:80", "[::1%lo0]:80".
  1917. func AddMissingPort(addr string, isTLS bool) string {
  1918. addrLen := len(addr)
  1919. if addrLen == 0 {
  1920. return addr
  1921. }
  1922. isIP6 := addr[0] == '['
  1923. if isIP6 {
  1924. // if the IPv6 has opening bracket but closing bracket is the last char then it doesn't have a port
  1925. isIP6WithoutPort := addr[addrLen-1] == ']'
  1926. if !isIP6WithoutPort {
  1927. return addr
  1928. }
  1929. } else { // IPv4
  1930. columnPos := strings.LastIndexByte(addr, ':')
  1931. if columnPos > 0 {
  1932. return addr
  1933. }
  1934. }
  1935. port := ":80"
  1936. if isTLS {
  1937. port = ":443"
  1938. }
  1939. return addr + port
  1940. }
  1941. // A wantConn records state about a wanted connection
  1942. // (that is, an active call to getConn).
  1943. // The conn may be gotten by dialing or by finding an idle connection,
  1944. // or a cancellation may make the conn no longer wanted.
  1945. // These three options are racing against each other and use
  1946. // wantConn to coordinate and agree about the winning outcome.
  1947. //
  1948. // Inspired by net/http/transport.go.
  1949. type wantConn struct {
  1950. err error
  1951. ready chan struct{}
  1952. conn *clientConn
  1953. mu sync.Mutex // protects conn, err, close(ready)
  1954. }
  1955. // waiting reports whether w is still waiting for an answer (connection or error).
  1956. func (w *wantConn) waiting() bool {
  1957. select {
  1958. case <-w.ready:
  1959. return false
  1960. default:
  1961. return true
  1962. }
  1963. }
  1964. // tryDeliver attempts to deliver conn, err to w and reports whether it succeeded.
  1965. func (w *wantConn) tryDeliver(conn *clientConn, err error) bool {
  1966. w.mu.Lock()
  1967. defer w.mu.Unlock()
  1968. if w.conn != nil || w.err != nil {
  1969. return false
  1970. }
  1971. w.conn = conn
  1972. w.err = err
  1973. if w.conn == nil && w.err == nil {
  1974. panic("fasthttp: internal error: misuse of tryDeliver")
  1975. }
  1976. close(w.ready)
  1977. return true
  1978. }
  1979. // cancel marks w as no longer wanting a result (for example, due to cancellation).
  1980. // If a connection has been delivered already, cancel returns it with c.releaseConn.
  1981. func (w *wantConn) cancel(c *HostClient, err error) {
  1982. w.mu.Lock()
  1983. if w.conn == nil && w.err == nil {
  1984. close(w.ready) // catch misbehavior in future delivery
  1985. }
  1986. conn := w.conn
  1987. w.conn = nil
  1988. w.err = err
  1989. w.mu.Unlock()
  1990. if conn != nil {
  1991. c.ReleaseConn(conn)
  1992. }
  1993. }
  1994. // A wantConnQueue is a queue of wantConns.
  1995. //
  1996. // Inspired by net/http/transport.go.
  1997. type wantConnQueue struct {
  1998. // This is a queue, not a dequeue.
  1999. // It is split into two stages - head[headPos:] and tail.
  2000. // popFront is trivial (headPos++) on the first stage, and
  2001. // pushBack is trivial (append) on the second stage.
  2002. // If the first stage is empty, popFront can swap the
  2003. // first and second stages to remedy the situation.
  2004. //
  2005. // This two-stage split is analogous to the use of two lists
  2006. // in Okasaki's purely functional queue but without the
  2007. // overhead of reversing the list when swapping stages.
  2008. head []*wantConn
  2009. tail []*wantConn
  2010. headPos int
  2011. // failedWaiters is the number of waiters in the head or tail queue,
  2012. // but is invalid.
  2013. // These state waiters cannot truly be considered as waiters; the current
  2014. // implementation does not immediately remove them when they become
  2015. // invalid but instead only marks them.
  2016. failedWaiters atomic.Int64
  2017. }
  2018. // len returns the number of items in the queue.
  2019. func (q *wantConnQueue) len() int {
  2020. return len(q.head) - q.headPos + len(q.tail) - int(q.failedWaiters.Load())
  2021. }
  2022. // pushBack adds w to the back of the queue.
  2023. func (q *wantConnQueue) pushBack(w *wantConn) {
  2024. q.tail = append(q.tail, w)
  2025. }
  2026. // popFront removes and returns the wantConn at the front of the queue.
  2027. func (q *wantConnQueue) popFront() *wantConn {
  2028. if q.headPos >= len(q.head) {
  2029. if len(q.tail) == 0 {
  2030. return nil
  2031. }
  2032. // Pick up tail as new head, clear tail.
  2033. q.head, q.headPos, q.tail = q.tail, 0, q.head[:0]
  2034. }
  2035. w := q.head[q.headPos]
  2036. q.head[q.headPos] = nil
  2037. q.headPos++
  2038. return w
  2039. }
  2040. // peekFront returns the wantConn at the front of the queue without removing it.
  2041. func (q *wantConnQueue) peekFront() *wantConn {
  2042. if q.headPos < len(q.head) {
  2043. return q.head[q.headPos]
  2044. }
  2045. if len(q.tail) > 0 {
  2046. return q.tail[0]
  2047. }
  2048. return nil
  2049. }
  2050. // clearFront pops any wantConns that are no longer waiting from the head of the
  2051. // queue, reporting whether any were popped.
  2052. func (q *wantConnQueue) clearFront() (cleaned bool) {
  2053. for {
  2054. w := q.peekFront()
  2055. if w == nil || w.waiting() {
  2056. return cleaned
  2057. }
  2058. q.popFront()
  2059. q.failedWaiters.Add(-1)
  2060. cleaned = true
  2061. }
  2062. }
  2063. // PipelineClient pipelines requests over a limited set of concurrent
  2064. // connections to the given Addr.
  2065. //
  2066. // This client may be used in highly loaded HTTP-based RPC systems for reducing
  2067. // context switches and network level overhead.
  2068. // See https://en.wikipedia.org/wiki/HTTP_pipelining for details.
  2069. //
  2070. // It is forbidden copying PipelineClient instances. Create new instances
  2071. // instead.
  2072. //
  2073. // It is safe calling PipelineClient methods from concurrently running
  2074. // goroutines.
  2075. type PipelineClient struct {
  2076. noCopy noCopy
  2077. // Logger for logging client errors.
  2078. //
  2079. // By default standard logger from log package is used.
  2080. Logger Logger
  2081. // Callback for connection establishing to the host.
  2082. //
  2083. // Default Dial is used if not set.
  2084. Dial DialFunc
  2085. // Optional TLS config.
  2086. TLSConfig *tls.Config
  2087. // Address of the host to connect to.
  2088. Addr string
  2089. // PipelineClient name. Used in User-Agent request header.
  2090. Name string
  2091. connClients []*pipelineConnClient
  2092. // The maximum number of concurrent connections to the Addr.
  2093. //
  2094. // A single connection is used by default.
  2095. MaxConns int
  2096. // The maximum number of pending pipelined requests over
  2097. // a single connection to Addr.
  2098. //
  2099. // DefaultMaxPendingRequests is used by default.
  2100. MaxPendingRequests int
  2101. // The maximum delay before sending pipelined requests as a batch
  2102. // to the server.
  2103. //
  2104. // By default requests are sent immediately to the server.
  2105. MaxBatchDelay time.Duration
  2106. // Idle connection to the host is closed after this duration.
  2107. //
  2108. // By default idle connection is closed after
  2109. // DefaultMaxIdleConnDuration.
  2110. MaxIdleConnDuration time.Duration
  2111. // Buffer size for responses' reading.
  2112. // This also limits the maximum header size.
  2113. //
  2114. // Default buffer size is used if 0.
  2115. ReadBufferSize int
  2116. // Buffer size for requests' writing.
  2117. //
  2118. // Default buffer size is used if 0.
  2119. WriteBufferSize int
  2120. // Maximum duration for full response reading (including body).
  2121. //
  2122. // By default response read timeout is unlimited.
  2123. ReadTimeout time.Duration
  2124. // Maximum duration for full request writing (including body).
  2125. //
  2126. // By default request write timeout is unlimited.
  2127. WriteTimeout time.Duration
  2128. connClientsLock sync.Mutex
  2129. // NoDefaultUserAgentHeader when set to true, causes the default
  2130. // User-Agent header to be excluded from the Request.
  2131. NoDefaultUserAgentHeader bool
  2132. // Attempt to connect to both ipv4 and ipv6 host addresses
  2133. // if set to true.
  2134. //
  2135. // This option is used only if default TCP dialer is used,
  2136. // i.e. if Dial is blank.
  2137. //
  2138. // By default client connects only to ipv4 addresses,
  2139. // since unfortunately ipv6 remains broken in many networks worldwide :)
  2140. DialDualStack bool
  2141. // Response header names are passed as-is without normalization
  2142. // if this option is set.
  2143. //
  2144. // Disabled header names' normalization may be useful only for proxying
  2145. // responses to other clients expecting case-sensitive
  2146. // header names. See https://github.com/valyala/fasthttp/issues/57
  2147. // for details.
  2148. //
  2149. // By default request and response header names are normalized, i.e.
  2150. // The first letter and the first letters following dashes
  2151. // are uppercased, while all the other letters are lowercased.
  2152. // Examples:
  2153. //
  2154. // * HOST -> Host
  2155. // * content-type -> Content-Type
  2156. // * cONTENT-lenGTH -> Content-Length
  2157. DisableHeaderNamesNormalizing bool
  2158. // Path values are sent as-is without normalization
  2159. //
  2160. // Disabled path normalization may be useful for proxying incoming requests
  2161. // to servers that are expecting paths to be forwarded as-is.
  2162. //
  2163. // By default path values are normalized, i.e.
  2164. // extra slashes are removed, special characters are encoded.
  2165. DisablePathNormalizing bool
  2166. // Whether to use TLS (aka SSL or HTTPS) for host connections.
  2167. IsTLS bool
  2168. }
  2169. type pipelineConnClient struct {
  2170. noCopy noCopy
  2171. workPool sync.Pool
  2172. Logger Logger
  2173. Dial DialFunc
  2174. TLSConfig *tls.Config
  2175. chW chan *pipelineWork
  2176. chR chan *pipelineWork
  2177. tlsConfig *tls.Config
  2178. Addr string
  2179. Name string
  2180. MaxPendingRequests int
  2181. MaxBatchDelay time.Duration
  2182. MaxIdleConnDuration time.Duration
  2183. ReadBufferSize int
  2184. WriteBufferSize int
  2185. ReadTimeout time.Duration
  2186. WriteTimeout time.Duration
  2187. chLock sync.Mutex
  2188. tlsConfigLock sync.Mutex
  2189. NoDefaultUserAgentHeader bool
  2190. DialDualStack bool
  2191. DisableHeaderNamesNormalizing bool
  2192. DisablePathNormalizing bool
  2193. IsTLS bool
  2194. }
  2195. type pipelineWork struct {
  2196. respCopy Response
  2197. deadline time.Time
  2198. err error
  2199. req *Request
  2200. resp *Response
  2201. t *time.Timer
  2202. done chan struct{}
  2203. reqCopy Request
  2204. }
  2205. // DoTimeout performs the given request and waits for response during
  2206. // the given timeout duration.
  2207. //
  2208. // Request must contain at least non-zero RequestURI with full url (including
  2209. // scheme and host) or non-zero Host header + RequestURI.
  2210. //
  2211. // The function doesn't follow redirects.
  2212. //
  2213. // Response is ignored if resp is nil.
  2214. //
  2215. // ErrTimeout is returned if the response wasn't returned during
  2216. // the given timeout.
  2217. //
  2218. // It is recommended obtaining req and resp via AcquireRequest
  2219. // and AcquireResponse in performance-critical code.
  2220. func (c *PipelineClient) DoTimeout(req *Request, resp *Response, timeout time.Duration) error {
  2221. return c.DoDeadline(req, resp, time.Now().Add(timeout))
  2222. }
  2223. // DoDeadline performs the given request and waits for response until
  2224. // the given deadline.
  2225. //
  2226. // Request must contain at least non-zero RequestURI with full url (including
  2227. // scheme and host) or non-zero Host header + RequestURI.
  2228. //
  2229. // The function doesn't follow redirects.
  2230. //
  2231. // Response is ignored if resp is nil.
  2232. //
  2233. // ErrTimeout is returned if the response wasn't returned until
  2234. // the given deadline.
  2235. //
  2236. // It is recommended obtaining req and resp via AcquireRequest
  2237. // and AcquireResponse in performance-critical code.
  2238. func (c *PipelineClient) DoDeadline(req *Request, resp *Response, deadline time.Time) error {
  2239. return c.getConnClient().DoDeadline(req, resp, deadline)
  2240. }
  2241. func (c *pipelineConnClient) DoDeadline(req *Request, resp *Response, deadline time.Time) error {
  2242. c.init()
  2243. timeout := time.Until(deadline)
  2244. if timeout <= 0 {
  2245. return ErrTimeout
  2246. }
  2247. if c.DisablePathNormalizing {
  2248. req.URI().DisablePathNormalizing = true
  2249. }
  2250. userAgentOld := req.Header.UserAgent()
  2251. if len(userAgentOld) == 0 {
  2252. userAgent := c.Name
  2253. if userAgent == "" && !c.NoDefaultUserAgentHeader {
  2254. userAgent = defaultUserAgent
  2255. }
  2256. if userAgent != "" {
  2257. req.Header.userAgent = append(req.Header.userAgent[:0], userAgent...)
  2258. }
  2259. }
  2260. w := c.acquirePipelineWork(timeout)
  2261. w.respCopy.Header.disableNormalizing = c.DisableHeaderNamesNormalizing
  2262. w.req = &w.reqCopy
  2263. w.resp = &w.respCopy
  2264. // Make a copy of the request in order to avoid data races on timeouts
  2265. req.copyToSkipBody(&w.reqCopy)
  2266. swapRequestBody(req, &w.reqCopy)
  2267. // Put the request to outgoing queue
  2268. select {
  2269. case c.chW <- w:
  2270. // Fast path: len(c.ch) < cap(c.ch)
  2271. default:
  2272. // Slow path
  2273. select {
  2274. case c.chW <- w:
  2275. case <-w.t.C:
  2276. c.releasePipelineWork(w)
  2277. return ErrTimeout
  2278. }
  2279. }
  2280. // Wait for the response
  2281. var err error
  2282. select {
  2283. case <-w.done:
  2284. if resp != nil {
  2285. w.respCopy.copyToSkipBody(resp)
  2286. swapResponseBody(resp, &w.respCopy)
  2287. }
  2288. err = w.err
  2289. c.releasePipelineWork(w)
  2290. case <-w.t.C:
  2291. err = ErrTimeout
  2292. }
  2293. return err
  2294. }
  2295. func (c *pipelineConnClient) acquirePipelineWork(timeout time.Duration) (w *pipelineWork) {
  2296. v := c.workPool.Get()
  2297. if v != nil {
  2298. w = v.(*pipelineWork)
  2299. } else {
  2300. w = &pipelineWork{
  2301. done: make(chan struct{}, 1),
  2302. }
  2303. }
  2304. if timeout > 0 {
  2305. if w.t == nil {
  2306. w.t = time.NewTimer(timeout)
  2307. } else {
  2308. w.t.Reset(timeout)
  2309. }
  2310. w.deadline = time.Now().Add(timeout)
  2311. } else {
  2312. w.deadline = zeroTime
  2313. }
  2314. return w
  2315. }
  2316. func (c *pipelineConnClient) releasePipelineWork(w *pipelineWork) {
  2317. if w.t != nil {
  2318. w.t.Stop()
  2319. }
  2320. w.reqCopy.Reset()
  2321. w.respCopy.Reset()
  2322. w.req = nil
  2323. w.resp = nil
  2324. w.err = nil
  2325. c.workPool.Put(w)
  2326. }
  2327. // Do performs the given http request and sets the corresponding response.
  2328. //
  2329. // Request must contain at least non-zero RequestURI with full url (including
  2330. // scheme and host) or non-zero Host header + RequestURI.
  2331. //
  2332. // The function doesn't follow redirects. Use Get* for following redirects.
  2333. //
  2334. // Response is ignored if resp is nil.
  2335. //
  2336. // It is recommended obtaining req and resp via AcquireRequest
  2337. // and AcquireResponse in performance-critical code.
  2338. func (c *PipelineClient) Do(req *Request, resp *Response) error {
  2339. return c.getConnClient().Do(req, resp)
  2340. }
  2341. func (c *pipelineConnClient) Do(req *Request, resp *Response) error {
  2342. c.init()
  2343. if c.DisablePathNormalizing {
  2344. req.URI().DisablePathNormalizing = true
  2345. }
  2346. userAgentOld := req.Header.UserAgent()
  2347. if len(userAgentOld) == 0 {
  2348. userAgent := c.Name
  2349. if userAgent == "" && !c.NoDefaultUserAgentHeader {
  2350. userAgent = defaultUserAgent
  2351. }
  2352. if userAgent != "" {
  2353. req.Header.userAgent = append(req.Header.userAgent[:0], userAgent...)
  2354. }
  2355. }
  2356. w := c.acquirePipelineWork(0)
  2357. w.req = req
  2358. if resp != nil {
  2359. resp.Header.disableNormalizing = c.DisableHeaderNamesNormalizing
  2360. w.resp = resp
  2361. } else {
  2362. w.resp = &w.respCopy
  2363. }
  2364. // Put the request to outgoing queue
  2365. select {
  2366. case c.chW <- w:
  2367. default:
  2368. // Try substituting the oldest w with the current one.
  2369. select {
  2370. case wOld := <-c.chW:
  2371. wOld.err = ErrPipelineOverflow
  2372. wOld.done <- struct{}{}
  2373. default:
  2374. }
  2375. select {
  2376. case c.chW <- w:
  2377. default:
  2378. c.releasePipelineWork(w)
  2379. return ErrPipelineOverflow
  2380. }
  2381. }
  2382. // Wait for the response
  2383. <-w.done
  2384. err := w.err
  2385. c.releasePipelineWork(w)
  2386. return err
  2387. }
  2388. func (c *PipelineClient) getConnClient() *pipelineConnClient {
  2389. c.connClientsLock.Lock()
  2390. cc := c.getConnClientUnlocked()
  2391. c.connClientsLock.Unlock()
  2392. return cc
  2393. }
  2394. func (c *PipelineClient) getConnClientUnlocked() *pipelineConnClient {
  2395. if len(c.connClients) == 0 {
  2396. return c.newConnClient()
  2397. }
  2398. // Return the client with the minimum number of pending requests.
  2399. minCC := c.connClients[0]
  2400. minReqs := minCC.PendingRequests()
  2401. if minReqs == 0 {
  2402. return minCC
  2403. }
  2404. for i := 1; i < len(c.connClients); i++ {
  2405. cc := c.connClients[i]
  2406. reqs := cc.PendingRequests()
  2407. if reqs == 0 {
  2408. return cc
  2409. }
  2410. if reqs < minReqs {
  2411. minCC = cc
  2412. minReqs = reqs
  2413. }
  2414. }
  2415. maxConns := c.MaxConns
  2416. if maxConns <= 0 {
  2417. maxConns = 1
  2418. }
  2419. if len(c.connClients) < maxConns {
  2420. return c.newConnClient()
  2421. }
  2422. return minCC
  2423. }
  2424. func (c *PipelineClient) newConnClient() *pipelineConnClient {
  2425. cc := &pipelineConnClient{
  2426. Addr: c.Addr,
  2427. Name: c.Name,
  2428. NoDefaultUserAgentHeader: c.NoDefaultUserAgentHeader,
  2429. MaxPendingRequests: c.MaxPendingRequests,
  2430. MaxBatchDelay: c.MaxBatchDelay,
  2431. Dial: c.Dial,
  2432. DialDualStack: c.DialDualStack,
  2433. DisableHeaderNamesNormalizing: c.DisableHeaderNamesNormalizing,
  2434. DisablePathNormalizing: c.DisablePathNormalizing,
  2435. IsTLS: c.IsTLS,
  2436. TLSConfig: c.TLSConfig,
  2437. MaxIdleConnDuration: c.MaxIdleConnDuration,
  2438. ReadBufferSize: c.ReadBufferSize,
  2439. WriteBufferSize: c.WriteBufferSize,
  2440. ReadTimeout: c.ReadTimeout,
  2441. WriteTimeout: c.WriteTimeout,
  2442. Logger: c.Logger,
  2443. }
  2444. c.connClients = append(c.connClients, cc)
  2445. return cc
  2446. }
  2447. // ErrPipelineOverflow may be returned from PipelineClient.Do*
  2448. // if the requests' queue is overflowed.
  2449. var ErrPipelineOverflow = errors.New("pipelined requests' queue has been overflowed. Increase MaxConns and/or MaxPendingRequests")
  2450. // DefaultMaxPendingRequests is the default value
  2451. // for PipelineClient.MaxPendingRequests.
  2452. const DefaultMaxPendingRequests = 1024
  2453. func (c *pipelineConnClient) init() {
  2454. c.chLock.Lock()
  2455. if c.chR == nil {
  2456. maxPendingRequests := c.MaxPendingRequests
  2457. if maxPendingRequests <= 0 {
  2458. maxPendingRequests = DefaultMaxPendingRequests
  2459. }
  2460. c.chR = make(chan *pipelineWork, maxPendingRequests)
  2461. if c.chW == nil {
  2462. c.chW = make(chan *pipelineWork, maxPendingRequests)
  2463. }
  2464. go func() {
  2465. // Keep restarting the worker if it fails (connection errors for example).
  2466. for {
  2467. if err := c.worker(); err != nil {
  2468. c.logger().Printf("error in PipelineClient(%q): %v", c.Addr, err)
  2469. if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
  2470. // Throttle client reconnections on timeout errors
  2471. time.Sleep(time.Second)
  2472. }
  2473. } else {
  2474. c.chLock.Lock()
  2475. stop := len(c.chR) == 0 && len(c.chW) == 0
  2476. if !stop {
  2477. c.chR = nil
  2478. c.chW = nil
  2479. }
  2480. c.chLock.Unlock()
  2481. if stop {
  2482. break
  2483. }
  2484. }
  2485. }
  2486. }()
  2487. }
  2488. c.chLock.Unlock()
  2489. }
  2490. func (c *pipelineConnClient) worker() error {
  2491. tlsConfig := c.cachedTLSConfig()
  2492. conn, err := dialAddr(c.Addr, c.Dial, nil, c.DialDualStack, c.IsTLS, tlsConfig, 0, c.WriteTimeout)
  2493. if err != nil {
  2494. return err
  2495. }
  2496. // Start reader and writer
  2497. stopW := make(chan struct{})
  2498. doneW := make(chan error)
  2499. go func() {
  2500. doneW <- c.writer(conn, stopW)
  2501. }()
  2502. stopR := make(chan struct{})
  2503. doneR := make(chan error)
  2504. go func() {
  2505. doneR <- c.reader(conn, stopR)
  2506. }()
  2507. // Wait until reader and writer are stopped
  2508. select {
  2509. case err = <-doneW:
  2510. conn.Close()
  2511. close(stopR)
  2512. <-doneR
  2513. case err = <-doneR:
  2514. conn.Close()
  2515. close(stopW)
  2516. <-doneW
  2517. }
  2518. // Notify pending readers
  2519. for len(c.chR) > 0 {
  2520. w := <-c.chR
  2521. w.err = errPipelineConnStopped
  2522. w.done <- struct{}{}
  2523. }
  2524. return err
  2525. }
  2526. func (c *pipelineConnClient) cachedTLSConfig() *tls.Config {
  2527. if !c.IsTLS {
  2528. return nil
  2529. }
  2530. c.tlsConfigLock.Lock()
  2531. cfg := c.tlsConfig
  2532. if cfg == nil {
  2533. cfg = newClientTLSConfig(c.TLSConfig, c.Addr)
  2534. c.tlsConfig = cfg
  2535. }
  2536. c.tlsConfigLock.Unlock()
  2537. return cfg
  2538. }
  2539. func (c *pipelineConnClient) writer(conn net.Conn, stopCh <-chan struct{}) error {
  2540. writeBufferSize := c.WriteBufferSize
  2541. if writeBufferSize <= 0 {
  2542. writeBufferSize = defaultWriteBufferSize
  2543. }
  2544. bw := bufio.NewWriterSize(conn, writeBufferSize)
  2545. defer bw.Flush()
  2546. chR := c.chR
  2547. chW := c.chW
  2548. writeTimeout := c.WriteTimeout
  2549. maxIdleConnDuration := c.MaxIdleConnDuration
  2550. if maxIdleConnDuration <= 0 {
  2551. maxIdleConnDuration = DefaultMaxIdleConnDuration
  2552. }
  2553. maxBatchDelay := c.MaxBatchDelay
  2554. var (
  2555. stopTimer = time.NewTimer(time.Hour)
  2556. flushTimer = time.NewTimer(time.Hour)
  2557. flushTimerCh <-chan time.Time
  2558. instantTimerCh = make(chan time.Time)
  2559. w *pipelineWork
  2560. err error
  2561. )
  2562. close(instantTimerCh)
  2563. for {
  2564. againChW:
  2565. select {
  2566. case w = <-chW:
  2567. // Fast path: len(chW) > 0
  2568. default:
  2569. // Slow path
  2570. stopTimer.Reset(maxIdleConnDuration)
  2571. select {
  2572. case w = <-chW:
  2573. case <-stopTimer.C:
  2574. return nil
  2575. case <-stopCh:
  2576. return nil
  2577. case <-flushTimerCh:
  2578. if err = bw.Flush(); err != nil {
  2579. return err
  2580. }
  2581. flushTimerCh = nil
  2582. goto againChW
  2583. }
  2584. }
  2585. if !w.deadline.IsZero() && time.Since(w.deadline) >= 0 {
  2586. w.err = ErrTimeout
  2587. w.done <- struct{}{}
  2588. continue
  2589. }
  2590. w.resp.ParseNetConn(conn)
  2591. if writeTimeout > 0 {
  2592. // Set Deadline every time, since golang has fixed the performance issue
  2593. // See https://github.com/golang/go/issues/15133#issuecomment-271571395 for details
  2594. currentTime := time.Now()
  2595. if err = conn.SetWriteDeadline(currentTime.Add(writeTimeout)); err != nil {
  2596. w.err = err
  2597. w.done <- struct{}{}
  2598. return err
  2599. }
  2600. }
  2601. if err = w.req.Write(bw); err != nil {
  2602. w.err = err
  2603. w.done <- struct{}{}
  2604. return err
  2605. }
  2606. if flushTimerCh == nil && (len(chW) == 0 || len(chR) == cap(chR)) {
  2607. if maxBatchDelay > 0 {
  2608. flushTimer.Reset(maxBatchDelay)
  2609. flushTimerCh = flushTimer.C
  2610. } else {
  2611. flushTimerCh = instantTimerCh
  2612. }
  2613. }
  2614. againChR:
  2615. select {
  2616. case chR <- w:
  2617. // Fast path: len(chR) < cap(chR)
  2618. default:
  2619. // Slow path
  2620. select {
  2621. case chR <- w:
  2622. case <-stopCh:
  2623. w.err = errPipelineConnStopped
  2624. w.done <- struct{}{}
  2625. return nil
  2626. case <-flushTimerCh:
  2627. if err = bw.Flush(); err != nil {
  2628. w.err = err
  2629. w.done <- struct{}{}
  2630. return err
  2631. }
  2632. flushTimerCh = nil
  2633. goto againChR
  2634. }
  2635. }
  2636. }
  2637. }
  2638. func (c *pipelineConnClient) reader(conn net.Conn, stopCh <-chan struct{}) error {
  2639. readBufferSize := c.ReadBufferSize
  2640. if readBufferSize <= 0 {
  2641. readBufferSize = defaultReadBufferSize
  2642. }
  2643. br := bufio.NewReaderSize(conn, readBufferSize)
  2644. chR := c.chR
  2645. readTimeout := c.ReadTimeout
  2646. var (
  2647. w *pipelineWork
  2648. err error
  2649. )
  2650. for {
  2651. select {
  2652. case w = <-chR:
  2653. // Fast path: len(chR) > 0
  2654. default:
  2655. // Slow path
  2656. select {
  2657. case w = <-chR:
  2658. case <-stopCh:
  2659. return nil
  2660. }
  2661. }
  2662. if readTimeout > 0 {
  2663. // Set Deadline every time, since golang has fixed the performance issue
  2664. // See https://github.com/golang/go/issues/15133#issuecomment-271571395 for details
  2665. currentTime := time.Now()
  2666. if err = conn.SetReadDeadline(currentTime.Add(readTimeout)); err != nil {
  2667. w.err = err
  2668. w.done <- struct{}{}
  2669. return err
  2670. }
  2671. }
  2672. if err = w.resp.Read(br); err != nil {
  2673. w.err = err
  2674. w.done <- struct{}{}
  2675. return err
  2676. }
  2677. w.done <- struct{}{}
  2678. }
  2679. }
  2680. func (c *pipelineConnClient) logger() Logger {
  2681. if c.Logger != nil {
  2682. return c.Logger
  2683. }
  2684. return defaultLogger
  2685. }
  2686. // PendingRequests returns the current number of pending requests pipelined
  2687. // to the server.
  2688. //
  2689. // This number may exceed MaxPendingRequests*MaxConns by up to two times, since
  2690. // each connection to the server may keep up to MaxPendingRequests requests
  2691. // in the queue before sending them to the server.
  2692. //
  2693. // This function may be used for balancing load among multiple PipelineClient
  2694. // instances.
  2695. func (c *PipelineClient) PendingRequests() int {
  2696. c.connClientsLock.Lock()
  2697. n := 0
  2698. for _, cc := range c.connClients {
  2699. n += cc.PendingRequests()
  2700. }
  2701. c.connClientsLock.Unlock()
  2702. return n
  2703. }
  2704. func (c *pipelineConnClient) PendingRequests() int {
  2705. c.init()
  2706. c.chLock.Lock()
  2707. n := len(c.chR) + len(c.chW)
  2708. c.chLock.Unlock()
  2709. return n
  2710. }
  2711. var errPipelineConnStopped = errors.New("pipeline connection has been stopped")
  2712. var DefaultTransport RoundTripper = &transport{}
  2713. type transport struct{}
  2714. func (t *transport) RoundTrip(hc *HostClient, req *Request, resp *Response) (retry bool, err error) {
  2715. customSkipBody := resp.SkipBody
  2716. customStreamBody := resp.StreamBody
  2717. var deadline time.Time
  2718. if req.timeout > 0 {
  2719. deadline = time.Now().Add(req.timeout)
  2720. }
  2721. cc, err := hc.AcquireConn(req.timeout, req.ConnectionClose())
  2722. if err != nil {
  2723. return false, err
  2724. }
  2725. conn := cc.c
  2726. resp.ParseNetConn(conn)
  2727. writeDeadline := deadline
  2728. if hc.WriteTimeout > 0 {
  2729. tmpWriteDeadline := time.Now().Add(hc.WriteTimeout)
  2730. if writeDeadline.IsZero() || tmpWriteDeadline.Before(writeDeadline) {
  2731. writeDeadline = tmpWriteDeadline
  2732. }
  2733. }
  2734. if err = conn.SetWriteDeadline(writeDeadline); err != nil {
  2735. hc.CloseConn(cc)
  2736. return true, err
  2737. }
  2738. resetConnection := false
  2739. if hc.MaxConnDuration > 0 && time.Since(cc.createdTime) > hc.MaxConnDuration && !req.ConnectionClose() {
  2740. req.SetConnectionClose()
  2741. resetConnection = true
  2742. }
  2743. bw := hc.AcquireWriter(conn)
  2744. err = req.Write(bw)
  2745. if resetConnection {
  2746. req.Header.ResetConnectionClose()
  2747. }
  2748. if err == nil {
  2749. err = bw.Flush()
  2750. }
  2751. hc.ReleaseWriter(bw)
  2752. // Return ErrTimeout on any timeout.
  2753. if x, ok := err.(interface{ Timeout() bool }); ok && x.Timeout() {
  2754. err = ErrTimeout
  2755. }
  2756. if err != nil {
  2757. hc.CloseConn(cc)
  2758. return true, err
  2759. }
  2760. readDeadline := deadline
  2761. if hc.ReadTimeout > 0 {
  2762. tmpReadDeadline := time.Now().Add(hc.ReadTimeout)
  2763. if readDeadline.IsZero() || tmpReadDeadline.Before(readDeadline) {
  2764. readDeadline = tmpReadDeadline
  2765. }
  2766. }
  2767. if err = conn.SetReadDeadline(readDeadline); err != nil {
  2768. hc.CloseConn(cc)
  2769. return true, err
  2770. }
  2771. if customSkipBody || req.Header.IsHead() {
  2772. resp.SkipBody = true
  2773. }
  2774. if hc.DisableHeaderNamesNormalizing {
  2775. resp.Header.DisableNormalizing()
  2776. }
  2777. br := hc.AcquireReader(conn)
  2778. err = resp.ReadLimitBody(br, hc.MaxResponseBodySize)
  2779. if err != nil {
  2780. hc.ReleaseReader(br)
  2781. hc.CloseConn(cc)
  2782. // Don't retry in case of ErrBodyTooLarge since we will just get the same again.
  2783. needRetry := err != ErrBodyTooLarge
  2784. return needRetry, err
  2785. }
  2786. closeConn := resetConnection || req.ConnectionClose() || resp.ConnectionClose()
  2787. if customStreamBody && resp.bodyStream != nil {
  2788. rbs := resp.bodyStream
  2789. resp.bodyStream = newCloseReaderWithError(rbs, func(wErr error) error {
  2790. hc.ReleaseReader(br)
  2791. if r, ok := rbs.(*requestStream); ok {
  2792. releaseRequestStream(r)
  2793. }
  2794. if closeConn || resp.ConnectionClose() || wErr != nil {
  2795. hc.CloseConn(cc)
  2796. } else {
  2797. hc.ReleaseConn(cc)
  2798. }
  2799. return nil
  2800. })
  2801. return false, nil
  2802. }
  2803. hc.ReleaseReader(br)
  2804. if closeConn {
  2805. hc.CloseConn(cc)
  2806. } else {
  2807. hc.ReleaseConn(cc)
  2808. }
  2809. return false, nil
  2810. }