response.mx raw

   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  
   5  // HTTP Response reading and parsing.
   6  
   7  package http
   8  
   9  import (
  10  	"bufio"
  11  	"bytes"
  12  	"crypto/tls"
  13  	"errors"
  14  	"fmt"
  15  	"io"
  16  	"net/textproto"
  17  	"net/url"
  18  	"strconv"
  19  
  20  	"golang.org/x/net/http/httpguts"
  21  )
  22  
  23  var respExcludeHeader = map[string]bool{
  24  	"Content-Length":    true,
  25  	"Transfer-Encoding": true,
  26  	"Trailer":           true,
  27  }
  28  
  29  // Response represents the response from an HTTP request.
  30  //
  31  // The [Client] and [Transport] return Responses from servers once
  32  // the response headers have been received. The response body
  33  // is streamed on demand as the Body field is read.
  34  type Response struct {
  35  	Status     []byte // e.g. "200 OK"
  36  	StatusCode int    // e.g. 200
  37  	Proto      []byte // e.g. "HTTP/1.0"
  38  	ProtoMajor int    // e.g. 1
  39  	ProtoMinor int    // e.g. 0
  40  
  41  	// Header maps header keys to values. If the response had multiple
  42  	// headers with the same key, they may be concatenated, with comma
  43  	// delimiters.  (RFC 7230, section 3.2.2 requires that multiple headers
  44  	// be semantically equivalent to a comma-delimited sequence.) When
  45  	// Header values are duplicated by other fields in this struct (e.g.,
  46  	// ContentLength, TransferEncoding, Trailer), the field values are
  47  	// authoritative.
  48  	//
  49  	// Keys in the map are canonicalized (see CanonicalHeaderKey).
  50  	Header Header
  51  
  52  	// Body represents the response body.
  53  	//
  54  	// The response body is streamed on demand as the Body field
  55  	// is read. If the network connection fails or the server
  56  	// terminates the response, Body.Read calls return an error.
  57  	//
  58  	// The http Client and Transport guarantee that Body is always
  59  	// non-nil, even on responses without a body or responses with
  60  	// a zero-length body. It is the caller's responsibility to
  61  	// close Body. The default HTTP client's Transport may not
  62  	// reuse HTTP/1.x "keep-alive" TCP connections if the Body is
  63  	// not read to completion and closed.
  64  	//
  65  	// The Body is automatically dechunked if the server replied
  66  	// with a "chunked" Transfer-Encoding.
  67  	//
  68  	// As of Go 1.12, the Body will also implement io.Writer
  69  	// on a successful "101 Switching Protocols" response,
  70  	// as used by WebSockets and HTTP/2's "h2c" mode.
  71  	Body io.ReadCloser
  72  
  73  	// ContentLength records the length of the associated content. The
  74  	// value -1 indicates that the length is unknown. Unless Request.Method
  75  	// is "HEAD", values >= 0 indicate that the given number of bytes may
  76  	// be read from Body.
  77  	ContentLength int64
  78  
  79  	// Contains transfer encodings from outer-most to inner-most. Value is
  80  	// nil, means that "identity" encoding is used.
  81  	TransferEncoding [][]byte
  82  
  83  	// Close records whether the header directed that the connection be
  84  	// closed after reading Body. The value is advice for clients: neither
  85  	// ReadResponse nor Response.Write ever closes a connection.
  86  	Close bool
  87  
  88  	// Uncompressed reports whether the response was sent compressed but
  89  	// was decompressed by the http package. When true, reading from
  90  	// Body yields the uncompressed content instead of the compressed
  91  	// content actually set from the server, ContentLength is set to -1,
  92  	// and the "Content-Length" and "Content-Encoding" fields are deleted
  93  	// from the responseHeader. To get the original response from
  94  	// the server, set Transport.DisableCompression to true.
  95  	Uncompressed bool
  96  
  97  	// Trailer maps trailer keys to values in the same
  98  	// format as Header.
  99  	//
 100  	// The Trailer initially contains only nil values, one for
 101  	// each key specified in the server's "Trailer" header
 102  	// value. Those values are not added to Header.
 103  	//
 104  	// Trailer must not be accessed concurrently with Read calls
 105  	// on the Body.
 106  	//
 107  	// After Body.Read has returned io.EOF, Trailer will contain
 108  	// any trailer values sent by the server.
 109  	Trailer Header
 110  
 111  	// Request is the request that was sent to obtain this Response.
 112  	// Request's Body is nil (having already been consumed).
 113  	// This is only populated for Client requests.
 114  	Request *Request
 115  
 116  	// TLS contains information about the TLS connection on which the
 117  	// response was received. It is nil for unencrypted responses.
 118  	// The pointer is shared between responses and should not be
 119  	// modified.
 120  	TLS *tls.ConnectionState
 121  }
 122  
 123  // Cookies parses and returns the cookies set in the Set-Cookie headers.
 124  func (r *Response) Cookies() []*Cookie {
 125  	return readSetCookies(r.Header)
 126  }
 127  
 128  // ErrNoLocation is returned by the [Response.Location] method
 129  // when no Location header is present.
 130  var ErrNoLocation = errors.New("http: no Location header in response")
 131  
 132  // Location returns the URL of the response's "Location" header,
 133  // if present. Relative redirects are resolved relative to
 134  // [Response.Request]. [ErrNoLocation] is returned if no
 135  // Location header is present.
 136  func (r *Response) Location() (*url.URL, error) {
 137  	lv := r.Header.Get("Location")
 138  	if lv == "" {
 139  		return nil, ErrNoLocation
 140  	}
 141  	if r.Request != nil && r.Request.URL != nil {
 142  		return r.Request.URL.Parse(lv)
 143  	}
 144  	return url.Parse(lv)
 145  }
 146  
 147  // ReadResponse reads and returns an HTTP response from r.
 148  // The req parameter optionally specifies the [Request] that corresponds
 149  // to this [Response]. If nil, a GET request is assumed.
 150  // Clients must call resp.Body.Close when finished reading resp.Body.
 151  // After that call, clients can inspect resp.Trailer to find key/value
 152  // pairs included in the response trailer.
 153  func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) {
 154  	tp := textproto.NewReader(r)
 155  	resp := &Response{
 156  		Request: req,
 157  	}
 158  
 159  	// Parse the first line of the response.
 160  	line, err := tp.ReadLine()
 161  	if err != nil {
 162  		if err == io.EOF {
 163  			err = io.ErrUnexpectedEOF
 164  		}
 165  		return nil, err
 166  	}
 167  	proto, status, ok := bytes.Cut(line, " ")
 168  	if !ok {
 169  		return nil, badStringError("malformed HTTP response", line)
 170  	}
 171  	resp.Proto = proto
 172  	resp.Status = bytes.TrimLeft(status, " ")
 173  
 174  	statusCode, _, _ := bytes.Cut(resp.Status, " ")
 175  	if len(statusCode) != 3 {
 176  		return nil, badStringError("malformed HTTP status code", statusCode)
 177  	}
 178  	resp.StatusCode, err = strconv.Atoi(statusCode)
 179  	if err != nil || resp.StatusCode < 0 {
 180  		return nil, badStringError("malformed HTTP status code", statusCode)
 181  	}
 182  	if resp.ProtoMajor, resp.ProtoMinor, ok = ParseHTTPVersion(resp.Proto); !ok {
 183  		return nil, badStringError("malformed HTTP version", resp.Proto)
 184  	}
 185  
 186  	// Parse the response headers.
 187  	mimeHeader, err := tp.ReadMIMEHeader()
 188  	if err != nil {
 189  		if err == io.EOF {
 190  			err = io.ErrUnexpectedEOF
 191  		}
 192  		return nil, err
 193  	}
 194  	resp.Header = Header(mimeHeader)
 195  
 196  	fixPragmaCacheControl(resp.Header)
 197  
 198  	err = readTransfer(resp, r)
 199  	if err != nil {
 200  		return nil, err
 201  	}
 202  
 203  	return resp, nil
 204  }
 205  
 206  // RFC 7234, section 5.4: Should treat
 207  //
 208  //	Pragma: no-cache
 209  //
 210  // like
 211  //
 212  //	Cache-Control: no-cache
 213  func fixPragmaCacheControl(header Header) {
 214  	if hp, ok := header["Pragma"]; ok && len(hp) > 0 && hp[0] == "no-cache" {
 215  		if _, presentcc := header["Cache-Control"]; !presentcc {
 216  			header["Cache-Control"] = [][]byte{"no-cache"}
 217  		}
 218  	}
 219  }
 220  
 221  // ProtoAtLeast reports whether the HTTP protocol used
 222  // in the response is at least major.minor.
 223  func (r *Response) ProtoAtLeast(major, minor int) bool {
 224  	return r.ProtoMajor > major ||
 225  		r.ProtoMajor == major && r.ProtoMinor >= minor
 226  }
 227  
 228  // Write writes r to w in the HTTP/1.x server response format,
 229  // including the status line, headers, body, and optional trailer.
 230  //
 231  // This method consults the following fields of the response r:
 232  //
 233  //	StatusCode
 234  //	ProtoMajor
 235  //	ProtoMinor
 236  //	Request.Method
 237  //	TransferEncoding
 238  //	Trailer
 239  //	Body
 240  //	ContentLength
 241  //	Header, values for non-canonical keys will have unpredictable behavior
 242  //
 243  // The Response Body is closed after it is sent.
 244  func (r *Response) Write(w io.Writer) error {
 245  	// Status line
 246  	text := r.Status
 247  	if text == "" {
 248  		text = StatusText(r.StatusCode)
 249  		if text == "" {
 250  			text = "status code " + strconv.Itoa(r.StatusCode)
 251  		}
 252  	} else {
 253  		// Just to reduce stutter, if user set r.Status to "200 OK" and StatusCode to 200.
 254  		// Not important.
 255  		text = bytes.TrimPrefix(text, strconv.Itoa(r.StatusCode)+" ")
 256  	}
 257  
 258  	if _, err := fmt.Fprintf(w, "HTTP/%d.%d %03d %s\r\n", r.ProtoMajor, r.ProtoMinor, r.StatusCode, text); err != nil {
 259  		return err
 260  	}
 261  
 262  	// Clone it, so we can modify r1 as needed.
 263  	r1 := &Response{}
 264  	*r1 = *r
 265  	if r1.ContentLength == 0 && r1.Body != nil {
 266  		// Is it actually 0 length? Or just unknown?
 267  		var buf [1]byte
 268  		n, err := r1.Body.Read(buf[:])
 269  		if err != nil && err != io.EOF {
 270  			return err
 271  		}
 272  		if n == 0 {
 273  			// Reset it to a known zero reader, in case underlying one
 274  			// is unhappy being read repeatedly.
 275  			r1.Body = NoBody
 276  		} else {
 277  			r1.ContentLength = -1
 278  			r1.Body = struct {
 279  				io.Reader
 280  				io.Closer
 281  			}{
 282  				io.MultiReader(bytes.NewReader(buf[:1]), r.Body),
 283  				r.Body,
 284  			}
 285  		}
 286  	}
 287  	// If we're sending a non-chunked HTTP/1.1 response without a
 288  	// content-length, the only way to do that is the old HTTP/1.0
 289  	// way, by noting the EOF with a connection close, so we need
 290  	// to set Close.
 291  	if r1.ContentLength == -1 && !r1.Close && r1.ProtoAtLeast(1, 1) && !chunked(r1.TransferEncoding) && !r1.Uncompressed {
 292  		r1.Close = true
 293  	}
 294  
 295  	// Process Body,ContentLength,Close,Trailer
 296  	tw, err := newTransferWriter(r1)
 297  	if err != nil {
 298  		return err
 299  	}
 300  	err = tw.writeHeader(w, nil)
 301  	if err != nil {
 302  		return err
 303  	}
 304  
 305  	// Rest of header
 306  	err = r.Header.WriteSubset(w, respExcludeHeader)
 307  	if err != nil {
 308  		return err
 309  	}
 310  
 311  	// contentLengthAlreadySent may have been already sent for
 312  	// POST/PUT requests, even if zero length. See Issue 8180.
 313  	contentLengthAlreadySent := tw.shouldSendContentLength()
 314  	if r1.ContentLength == 0 && !chunked(r1.TransferEncoding) && !contentLengthAlreadySent && bodyAllowedForStatus(r.StatusCode) {
 315  		if _, err := io.WriteString(w, "Content-Length: 0\r\n"); err != nil {
 316  			return err
 317  		}
 318  	}
 319  
 320  	// End-of-header
 321  	if _, err := io.WriteString(w, "\r\n"); err != nil {
 322  		return err
 323  	}
 324  
 325  	// Write body and trailer
 326  	err = tw.writeBody(w)
 327  	if err != nil {
 328  		return err
 329  	}
 330  
 331  	// Success
 332  	return nil
 333  }
 334  
 335  func (r *Response) closeBody() {
 336  	if r.Body != nil {
 337  		r.Body.Close()
 338  	}
 339  }
 340  
 341  // bodyIsWritable reports whether the Body supports writing. The
 342  // Transport returns Writable bodies for 101 Switching Protocols
 343  // responses.
 344  // The Transport uses this method to determine whether a persistent
 345  // connection is done being managed from its perspective. Once we
 346  // return a writable response body to a user, the net/http package is
 347  // done managing that connection.
 348  func (r *Response) bodyIsWritable() bool {
 349  	_, ok := r.Body.(io.Writer)
 350  	return ok
 351  }
 352  
 353  // isProtocolSwitch reports whether the response code and header
 354  // indicate a successful protocol upgrade response.
 355  func (r *Response) isProtocolSwitch() bool {
 356  	return isProtocolSwitchResponse(r.StatusCode, r.Header)
 357  }
 358  
 359  // isProtocolSwitchResponse reports whether the response code and
 360  // response header indicate a successful protocol upgrade response.
 361  func isProtocolSwitchResponse(code int, h Header) bool {
 362  	return code == StatusSwitchingProtocols && isProtocolSwitchHeader(h)
 363  }
 364  
 365  // isProtocolSwitchHeader reports whether the request or response header
 366  // is for a protocol switch.
 367  func isProtocolSwitchHeader(h Header) bool {
 368  	return h.Get("Upgrade") != "" &&
 369  		httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade")
 370  }
 371