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.
16 var ErrPersistEOF
= &ProtocolError
{"persistent connection closed"}
18 // A ServerConn reads requests and sends responses over an underlying
19 // connection, until the HTTP keepalive logic commands an end. ServerConn
20 // does not close the underlying connection. Instead, the user calls Close
21 // and regains control over the connection. ServerConn supports pipe-lining,
22 // i.e. requests can be read out of sync (but in the same order) while the
23 // respective responses are sent.
24 type ServerConn
struct {
27 clsd
bool // indicates a graceful close
28 re
, we os
.Error
// read/write errors
29 lastBody io
.ReadCloser
31 lk sync
.Mutex
// protected read/write to re,we
34 // NewServerConn returns a new ServerConn reading and writing c. If r is not
35 // nil, it is the buffer to use when reading c.
36 func NewServerConn(c net
.Conn
, r
*bufio
.Reader
) *ServerConn
{
38 r
= bufio
.NewReader(c
)
40 return &ServerConn
{c
: c
, r
: r
}
43 // Close detaches the ServerConn and returns the underlying connection as well
44 // as the read-side bufio which may have some left over data. Close may be
45 // called before Read has signaled the end of the keep-alive logic. The user
46 // should not call Close while Read or Write is in progress.
47 func (sc
*ServerConn
) Close() (c net
.Conn
, r
*bufio
.Reader
) {
57 // Read returns the next request on the wire. An ErrPersistEOF is returned if
58 // it is gracefully determined that there are no more requests (e.g. after the
59 // first request on an HTTP/1.0 connection, or after a Connection:close on a
60 // HTTP/1.1 connection). Read can be called concurrently with Write, but not
62 func (sc
*ServerConn
) Read() (req
*Request
, err os
.Error
) {
65 if sc
.we
!= nil { // no point receiving if write-side broken or closed
75 // Make sure body is fully consumed, even if user does not call body.Close
76 if sc
.lastBody
!= nil {
77 // body.Close is assumed to be idempotent and multiple calls to
78 // it should return the error that its first invokation
80 err
= sc
.lastBody
.Close()
90 req
, err
= ReadRequest(sc
.r
)
94 if err
== io
.ErrUnexpectedEOF
{
95 // A close from the opposing client is treated as a
96 // graceful close, even if there was some unparse-able
97 // data before the close.
105 sc
.lastBody
= req
.Body
110 sc
.re
= ErrPersistEOF
116 // Pending returns the number of unanswered requests
117 // that have been received on the connection.
118 func (sc
*ServerConn
) Pending() int {
121 return sc
.nread
- sc
.nwritten
124 // Write writes a repsonse. To close the connection gracefully, set the
125 // Response.Close field to true. Write should be considered operational until
126 // it returns an error, regardless of any errors returned on the Read side.
127 // Write can be called concurrently with Read, but not with another Write.
128 func (sc
*ServerConn
) Write(resp
*Response
) os
.Error
{
136 if sc
.nread
<= sc
.nwritten
{
137 return os
.NewError("persist server pipe count")
141 // After signaling a keep-alive close, any pipelined unread
142 // requests will be lost. It is up to the user to drain them
145 sc
.re
= ErrPersistEOF
149 err
:= resp
.Write(sc
.c
)
161 // A ClientConn sends request and receives headers over an underlying
162 // connection, while respecting the HTTP keepalive logic. ClientConn is not
163 // responsible for closing the underlying connection. One must call Close to
164 // regain control of that connection and deal with it as desired.
165 type ClientConn
struct {
168 re
, we os
.Error
// read/write errors
169 lastBody io
.ReadCloser
171 reqm list
.List
// request methods in order of execution
172 lk sync
.Mutex
// protects read/write to reqm,re,we
175 // NewClientConn returns a new ClientConn reading and writing c. If r is not
176 // nil, it is the buffer to use when reading c.
177 func NewClientConn(c net
.Conn
, r
*bufio
.Reader
) *ClientConn
{
179 r
= bufio
.NewReader(c
)
181 return &ClientConn
{c
: c
, r
: r
}
184 // Close detaches the ClientConn and returns the underlying connection as well
185 // as the read-side bufio which may have some left over data. Close may be
186 // called before the user or Read have signaled the end of the keep-alive
187 // logic. The user should not call Close while Read or Write is in progress.
188 func (cc
*ClientConn
) Close() (c net
.Conn
, r
*bufio
.Reader
) {
199 // Write writes a request. An ErrPersistEOF error is returned if the connection
200 // has been closed in an HTTP keepalive sense. If req.Close equals true, the
201 // keepalive connection is logically closed after this request and the opposing
202 // server is informed. An ErrUnexpectedEOF indicates the remote closed the
203 // underlying TCP connection, which is usually considered as graceful close.
204 // Write can be called concurrently with Read, but not with another Write.
205 func (cc
*ClientConn
) Write(req
*Request
) os
.Error
{
208 if cc
.re
!= nil { // no point sending if read-side closed or broken
219 // We write the EOF to the write-side error, because there
220 // still might be some pipelined reads
222 cc
.we
= ErrPersistEOF
226 err
:= req
.Write(cc
.c
)
235 cc
.reqm
.PushBack(req
.Method
)
241 // Pending returns the number of unanswered requests
242 // that have been sent on the connection.
243 func (cc
*ClientConn
) Pending() int {
246 return cc
.nwritten
- cc
.nread
249 // Read reads the next response from the wire. A valid response might be
250 // returned together with an ErrPersistEOF, which means that the remote
251 // requested that this be the last request serviced. Read can be called
252 // concurrently with Write, but not with another Read.
253 func (cc
*ClientConn
) Read() (resp
*Response
, err os
.Error
) {
262 if cc
.nread
>= cc
.nwritten
{
263 return nil, os
.NewError("persist client pipe count")
266 // Make sure body is fully consumed, even if user does not call body.Close
267 if cc
.lastBody
!= nil {
268 // body.Close is assumed to be idempotent and multiple calls to
269 // it should return the error that its first invokation
271 err
= cc
.lastBody
.Close()
285 resp
, err
= ReadResponse(cc
.r
, m
.Value
.(string))
292 cc
.lastBody
= resp
.Body
299 cc
.re
= ErrPersistEOF
// don't send any more requests