...

Source file src/net/http/response.go

Documentation: net/http

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

View as plain text