func newConn(raw net.Conn, t *Transport, tls bool, addr string) *conn { buf := buffers.Get().([]byte) return &conn{ Reader: xo.NewReader(raw, buf[:bufferSize]), Writer: xo.NewWriter(raw, buf[bufferSize:]), raw: raw, buf: buf, t: t, tls: tls, addr: addr, } }
func (p *Proxy) serveHTTPS(conn net.Conn, addr string) error { rw := xo.NewReadWriter( xo.NewReader(conn, make([]byte, 4096)), xo.NewWriter(conn, make([]byte, 4096)), ) for { req, body, err := readRequest(rw) if err != nil { switch err { case heat.ErrRequestHeader: resp := statusResponse(404, "Malformed HTTP request header.") return writeResponse(rw, resp, req.Method) case heat.ErrRequestVersion: resp := statusResponse(505, "Unsupported HTTP version number.") return writeResponse(rw, resp, req.Method) // If the connection terminated cleanly, stop. case io.EOF: return nil // Any other error would be from the underlying connection, and // should be propagated. default: return err } } // Populate the scheme and remote address. req.Scheme = "https" req.Remote = addr // Will the client close this connection after receiving a response? closing := heat.Closing(req.Major, req.Minor, req.Fields) // Forward the request to the upstream server. resp, err := p.forward(req) if err != nil { resp = statusResponse(500, "Round-trip to upstream failed: %s.", err) } // Are we closing the connection after sending the response? if !closing && (body == nil || body.LastError() == io.EOF) { resp.Fields.Set("Connection", "keep-alive") } else { resp.Fields.Set("Connection", "close") closing = true } // Write the response. err = writeResponse(rw, resp, req.Method) if err != nil { return err } // Stop if the connection isn't keep-alive. if closing { return nil } } }
func (p *Proxy) serveHTTP(conn net.Conn) error { rw := xo.NewReadWriter( xo.NewReader(conn, make([]byte, 4096)), xo.NewWriter(conn, make([]byte, 4096)), ) for { // Read the next request. req, body, err := readRequest(rw) if err != nil { switch err { case heat.ErrRequestHeader: resp := statusResponse(404, "Malformed HTTP request header.") return writeResponse(rw, resp, req.Method) case heat.ErrRequestVersion: resp := statusResponse(505, "Unsupported HTTP version number.") return writeResponse(rw, resp, req.Method) // If the connection terminated cleanly, stop. case io.EOF: return nil // Any other error would be from the underlying connection, and // should be propagated. default: return err } } // Support CONNECT tunneling. if req.Method == "CONNECT" { return p.connect(conn, rw, req) } // Will the client close this connection after receiving a response? closing := heat.Closing(req.Major, req.Minor, req.Fields) // Fetch the actual response from the upstream server. resp, err := p.proxy(req) if err != nil { resp := statusResponse(500, "Unknown error: %s.", err) return writeResponse(rw, resp, req.Method) } // Are we closing the connection after sending the response? if !closing && (body == nil || body.LastError() == io.EOF) { resp.Fields.Set("Connection", "keep-alive") } else { resp.Fields.Set("Connection", "close") closing = true } // Write the response. err = writeResponse(rw, resp, req.Method) if err != nil { return err } // Stop if the connection isn't keep-alive. if closing { return nil } } }