persist.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package httputil
  5. import (
  6. "bufio"
  7. "errors"
  8. "io"
  9. "net"
  10. "net/http"
  11. "net/textproto"
  12. "sync"
  13. )
  14. var (
  15. // Deprecated: No longer used.
  16. ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"}
  17. // Deprecated: No longer used.
  18. ErrClosed = &http.ProtocolError{ErrorString: "connection closed by user"}
  19. // Deprecated: No longer used.
  20. ErrPipeline = &http.ProtocolError{ErrorString: "pipeline error"}
  21. )
  22. // This is an API usage error - the local side is closed.
  23. // ErrPersistEOF (above) reports that the remote side is closed.
  24. var errClosed = errors.New("i/o operation on closed connection")
  25. // ServerConn is an artifact of Go's early HTTP implementation.
  26. // It is low-level, old, and unused by Go's current HTTP stack.
  27. // We should have deleted it before Go 1.
  28. //
  29. // Deprecated: Use the Server in package net/http instead.
  30. type ServerConn struct {
  31. mu sync.Mutex // read-write protects the following fields
  32. c net.Conn
  33. r *bufio.Reader
  34. re, we error // read/write errors
  35. lastbody io.ReadCloser
  36. nread, nwritten int
  37. pipereq map[*http.Request]uint
  38. pipe textproto.Pipeline
  39. }
  40. // NewServerConn is an artifact of Go's early HTTP implementation.
  41. // It is low-level, old, and unused by Go's current HTTP stack.
  42. // We should have deleted it before Go 1.
  43. //
  44. // Deprecated: Use the Server in package net/http instead.
  45. func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
  46. if r == nil {
  47. r = bufio.NewReader(c)
  48. }
  49. return &ServerConn{c: c, r: r, pipereq: make(map[*http.Request]uint)}
  50. }
  51. // Hijack detaches the ServerConn and returns the underlying connection as well
  52. // as the read-side bufio which may have some left over data. Hijack may be
  53. // called before Read has signaled the end of the keep-alive logic. The user
  54. // should not call Hijack while Read or Write is in progress.
  55. func (sc *ServerConn) Hijack() (net.Conn, *bufio.Reader) {
  56. sc.mu.Lock()
  57. defer sc.mu.Unlock()
  58. c := sc.c
  59. r := sc.r
  60. sc.c = nil
  61. sc.r = nil
  62. return c, r
  63. }
  64. // Close calls Hijack and then also closes the underlying connection.
  65. func (sc *ServerConn) Close() error {
  66. c, _ := sc.Hijack()
  67. if c != nil {
  68. return c.Close()
  69. }
  70. return nil
  71. }
  72. // Read returns the next request on the wire. An ErrPersistEOF is returned if
  73. // it is gracefully determined that there are no more requests (e.g. after the
  74. // first request on an HTTP/1.0 connection, or after a Connection:close on a
  75. // HTTP/1.1 connection).
  76. func (sc *ServerConn) Read() (*http.Request, error) {
  77. var req *http.Request
  78. var err error
  79. // Ensure ordered execution of Reads and Writes
  80. id := sc.pipe.Next()
  81. sc.pipe.StartRequest(id)
  82. defer func() {
  83. sc.pipe.EndRequest(id)
  84. if req == nil {
  85. sc.pipe.StartResponse(id)
  86. sc.pipe.EndResponse(id)
  87. } else {
  88. // Remember the pipeline id of this request
  89. sc.mu.Lock()
  90. sc.pipereq[req] = id
  91. sc.mu.Unlock()
  92. }
  93. }()
  94. sc.mu.Lock()
  95. if sc.we != nil { // no point receiving if write-side broken or closed
  96. defer sc.mu.Unlock()
  97. return nil, sc.we
  98. }
  99. if sc.re != nil {
  100. defer sc.mu.Unlock()
  101. return nil, sc.re
  102. }
  103. if sc.r == nil { // connection closed by user in the meantime
  104. defer sc.mu.Unlock()
  105. return nil, errClosed
  106. }
  107. r := sc.r
  108. lastbody := sc.lastbody
  109. sc.lastbody = nil
  110. sc.mu.Unlock()
  111. // Make sure body is fully consumed, even if user does not call body.Close
  112. if lastbody != nil {
  113. // body.Close is assumed to be idempotent and multiple calls to
  114. // it should return the error that its first invocation
  115. // returned.
  116. err = lastbody.Close()
  117. if err != nil {
  118. sc.mu.Lock()
  119. defer sc.mu.Unlock()
  120. sc.re = err
  121. return nil, err
  122. }
  123. }
  124. req, err = http.ReadRequest(r)
  125. sc.mu.Lock()
  126. defer sc.mu.Unlock()
  127. if err != nil {
  128. if err == io.ErrUnexpectedEOF {
  129. // A close from the opposing client is treated as a
  130. // graceful close, even if there was some unparse-able
  131. // data before the close.
  132. sc.re = ErrPersistEOF
  133. return nil, sc.re
  134. } else {
  135. sc.re = err
  136. return req, err
  137. }
  138. }
  139. sc.lastbody = req.Body
  140. sc.nread++
  141. if req.Close {
  142. sc.re = ErrPersistEOF
  143. return req, sc.re
  144. }
  145. return req, err
  146. }
  147. // Pending returns the number of unanswered requests
  148. // that have been received on the connection.
  149. func (sc *ServerConn) Pending() int {
  150. sc.mu.Lock()
  151. defer sc.mu.Unlock()
  152. return sc.nread - sc.nwritten
  153. }
  154. // Write writes resp in response to req. To close the connection gracefully, set the
  155. // Response.Close field to true. Write should be considered operational until
  156. // it returns an error, regardless of any errors returned on the Read side.
  157. func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error {
  158. // Retrieve the pipeline ID of this request/response pair
  159. sc.mu.Lock()
  160. id, ok := sc.pipereq[req]
  161. delete(sc.pipereq, req)
  162. if !ok {
  163. sc.mu.Unlock()
  164. return ErrPipeline
  165. }
  166. sc.mu.Unlock()
  167. // Ensure pipeline order
  168. sc.pipe.StartResponse(id)
  169. defer sc.pipe.EndResponse(id)
  170. sc.mu.Lock()
  171. if sc.we != nil {
  172. defer sc.mu.Unlock()
  173. return sc.we
  174. }
  175. if sc.c == nil { // connection closed by user in the meantime
  176. defer sc.mu.Unlock()
  177. return ErrClosed
  178. }
  179. c := sc.c
  180. if sc.nread <= sc.nwritten {
  181. defer sc.mu.Unlock()
  182. return errors.New("persist server pipe count")
  183. }
  184. if resp.Close {
  185. // After signaling a keep-alive close, any pipelined unread
  186. // requests will be lost. It is up to the user to drain them
  187. // before signaling.
  188. sc.re = ErrPersistEOF
  189. }
  190. sc.mu.Unlock()
  191. err := resp.Write(c)
  192. sc.mu.Lock()
  193. defer sc.mu.Unlock()
  194. if err != nil {
  195. sc.we = err
  196. return err
  197. }
  198. sc.nwritten++
  199. return nil
  200. }
  201. // ClientConn is an artifact of Go's early HTTP implementation.
  202. // It is low-level, old, and unused by Go's current HTTP stack.
  203. // We should have deleted it before Go 1.
  204. //
  205. // Deprecated: Use Client or Transport in package net/http instead.
  206. type ClientConn struct {
  207. mu sync.Mutex // read-write protects the following fields
  208. c net.Conn
  209. r *bufio.Reader
  210. re, we error // read/write errors
  211. lastbody io.ReadCloser
  212. nread, nwritten int
  213. pipereq map[*http.Request]uint
  214. pipe textproto.Pipeline
  215. writeReq func(*http.Request, io.Writer) error
  216. }
  217. // NewClientConn is an artifact of Go's early HTTP implementation.
  218. // It is low-level, old, and unused by Go's current HTTP stack.
  219. // We should have deleted it before Go 1.
  220. //
  221. // Deprecated: Use the Client or Transport in package net/http instead.
  222. func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
  223. if r == nil {
  224. r = bufio.NewReader(c)
  225. }
  226. return &ClientConn{
  227. c: c,
  228. r: r,
  229. pipereq: make(map[*http.Request]uint),
  230. writeReq: (*http.Request).Write,
  231. }
  232. }
  233. // NewProxyClientConn is an artifact of Go's early HTTP implementation.
  234. // It is low-level, old, and unused by Go's current HTTP stack.
  235. // We should have deleted it before Go 1.
  236. //
  237. // Deprecated: Use the Client or Transport in package net/http instead.
  238. func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
  239. cc := NewClientConn(c, r)
  240. cc.writeReq = (*http.Request).WriteProxy
  241. return cc
  242. }
  243. // Hijack detaches the ClientConn and returns the underlying connection as well
  244. // as the read-side bufio which may have some left over data. Hijack may be
  245. // called before the user or Read have signaled the end of the keep-alive
  246. // logic. The user should not call Hijack while Read or Write is in progress.
  247. func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader) {
  248. cc.mu.Lock()
  249. defer cc.mu.Unlock()
  250. c = cc.c
  251. r = cc.r
  252. cc.c = nil
  253. cc.r = nil
  254. return
  255. }
  256. // Close calls Hijack and then also closes the underlying connection.
  257. func (cc *ClientConn) Close() error {
  258. c, _ := cc.Hijack()
  259. if c != nil {
  260. return c.Close()
  261. }
  262. return nil
  263. }
  264. // Write writes a request. An ErrPersistEOF error is returned if the connection
  265. // has been closed in an HTTP keep-alive sense. If req.Close equals true, the
  266. // keep-alive connection is logically closed after this request and the opposing
  267. // server is informed. An ErrUnexpectedEOF indicates the remote closed the
  268. // underlying TCP connection, which is usually considered as graceful close.
  269. func (cc *ClientConn) Write(req *http.Request) error {
  270. var err error
  271. // Ensure ordered execution of Writes
  272. id := cc.pipe.Next()
  273. cc.pipe.StartRequest(id)
  274. defer func() {
  275. cc.pipe.EndRequest(id)
  276. if err != nil {
  277. cc.pipe.StartResponse(id)
  278. cc.pipe.EndResponse(id)
  279. } else {
  280. // Remember the pipeline id of this request
  281. cc.mu.Lock()
  282. cc.pipereq[req] = id
  283. cc.mu.Unlock()
  284. }
  285. }()
  286. cc.mu.Lock()
  287. if cc.re != nil { // no point sending if read-side closed or broken
  288. defer cc.mu.Unlock()
  289. return cc.re
  290. }
  291. if cc.we != nil {
  292. defer cc.mu.Unlock()
  293. return cc.we
  294. }
  295. if cc.c == nil { // connection closed by user in the meantime
  296. defer cc.mu.Unlock()
  297. return errClosed
  298. }
  299. c := cc.c
  300. if req.Close {
  301. // We write the EOF to the write-side error, because there
  302. // still might be some pipelined reads
  303. cc.we = ErrPersistEOF
  304. }
  305. cc.mu.Unlock()
  306. err = cc.writeReq(req, c)
  307. cc.mu.Lock()
  308. defer cc.mu.Unlock()
  309. if err != nil {
  310. cc.we = err
  311. return err
  312. }
  313. cc.nwritten++
  314. return nil
  315. }
  316. // Pending returns the number of unanswered requests
  317. // that have been sent on the connection.
  318. func (cc *ClientConn) Pending() int {
  319. cc.mu.Lock()
  320. defer cc.mu.Unlock()
  321. return cc.nwritten - cc.nread
  322. }
  323. // Read reads the next response from the wire. A valid response might be
  324. // returned together with an ErrPersistEOF, which means that the remote
  325. // requested that this be the last request serviced. Read can be called
  326. // concurrently with Write, but not with another Read.
  327. func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error) {
  328. // Retrieve the pipeline ID of this request/response pair
  329. cc.mu.Lock()
  330. id, ok := cc.pipereq[req]
  331. delete(cc.pipereq, req)
  332. if !ok {
  333. cc.mu.Unlock()
  334. return nil, ErrPipeline
  335. }
  336. cc.mu.Unlock()
  337. // Ensure pipeline order
  338. cc.pipe.StartResponse(id)
  339. defer cc.pipe.EndResponse(id)
  340. cc.mu.Lock()
  341. if cc.re != nil {
  342. defer cc.mu.Unlock()
  343. return nil, cc.re
  344. }
  345. if cc.r == nil { // connection closed by user in the meantime
  346. defer cc.mu.Unlock()
  347. return nil, errClosed
  348. }
  349. r := cc.r
  350. lastbody := cc.lastbody
  351. cc.lastbody = nil
  352. cc.mu.Unlock()
  353. // Make sure body is fully consumed, even if user does not call body.Close
  354. if lastbody != nil {
  355. // body.Close is assumed to be idempotent and multiple calls to
  356. // it should return the error that its first invocation
  357. // returned.
  358. err = lastbody.Close()
  359. if err != nil {
  360. cc.mu.Lock()
  361. defer cc.mu.Unlock()
  362. cc.re = err
  363. return nil, err
  364. }
  365. }
  366. resp, err = http.ReadResponse(r, req)
  367. cc.mu.Lock()
  368. defer cc.mu.Unlock()
  369. if err != nil {
  370. cc.re = err
  371. return resp, err
  372. }
  373. cc.lastbody = resp.Body
  374. cc.nread++
  375. if resp.Close {
  376. cc.re = ErrPersistEOF // don't send any more requests
  377. return resp, cc.re
  378. }
  379. return resp, err
  380. }
  381. // Do is convenience method that writes a request and reads a response.
  382. func (cc *ClientConn) Do(req *http.Request) (*http.Response, error) {
  383. err := cc.Write(req)
  384. if err != nil {
  385. return nil, err
  386. }
  387. return cc.Read(req)
  388. }