Copyright 2009 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
HTTP Response reading and parsing.

package http

import (
	
	
	
	
	
	
	
	
	
	

	
)

var respExcludeHeader = map[string]bool{
	"Content-Length":    true,
	"Transfer-Encoding": true,
	"Trailer":           true,
}
Response represents the response from an HTTP request. The Client and Transport return Responses from servers once the response headers have been received. The response body is streamed on demand as the Body field is read.
type Response struct {
	Status     string // e.g. "200 OK"
	StatusCode int    // e.g. 200
	Proto      string // e.g. "HTTP/1.0"
	ProtoMajor int    // e.g. 1
	ProtoMinor int    // e.g. 0
Header maps header keys to values. If the response had multiple headers with the same key, they may be concatenated, with comma delimiters. (RFC 7230, section 3.2.2 requires that multiple headers be semantically equivalent to a comma-delimited sequence.) When Header values are duplicated by other fields in this struct (e.g., ContentLength, TransferEncoding, Trailer), the field values are authoritative. Keys in the map are canonicalized (see CanonicalHeaderKey).
Body represents the response body. The response body is streamed on demand as the Body field is read. If the network connection fails or the server terminates the response, Body.Read calls return an error. The http Client and Transport guarantee that Body is always non-nil, even on responses without a body or responses with a zero-length body. It is the caller's responsibility to close Body. The default HTTP client's Transport may not reuse HTTP/1.x "keep-alive" TCP connections if the Body is not read to completion and closed. The Body is automatically dechunked if the server replied with a "chunked" Transfer-Encoding. As of Go 1.12, the Body will also implement io.Writer on a successful "101 Switching Protocols" response, as used by WebSockets and HTTP/2's "h2c" mode.
ContentLength records the length of the associated content. The value -1 indicates that the length is unknown. Unless Request.Method is "HEAD", values >= 0 indicate that the given number of bytes may be read from Body.
Contains transfer encodings from outer-most to inner-most. Value is nil, means that "identity" encoding is used.
Close records whether the header directed that the connection be closed after reading Body. The value is advice for clients: neither ReadResponse nor Response.Write ever closes a connection.
Uncompressed reports whether the response was sent compressed but was decompressed by the http package. When true, reading from Body yields the uncompressed content instead of the compressed content actually set from the server, ContentLength is set to -1, and the "Content-Length" and "Content-Encoding" fields are deleted from the responseHeader. To get the original response from the server, set Transport.DisableCompression to true.
Trailer maps trailer keys to values in the same format as Header. The Trailer initially contains only nil values, one for each key specified in the server's "Trailer" header value. Those values are not added to Header. Trailer must not be accessed concurrently with Read calls on the Body. After Body.Read has returned io.EOF, Trailer will contain any trailer values sent by the server.
Request is the request that was sent to obtain this Response. Request's Body is nil (having already been consumed). This is only populated for Client requests.
TLS contains information about the TLS connection on which the response was received. It is nil for unencrypted responses. The pointer is shared between responses and should not be modified.
Cookies parses and returns the cookies set in the Set-Cookie headers.
func ( *Response) () []*Cookie {
	return readSetCookies(.Header)
}
ErrNoLocation is returned by Response's Location method when no Location header is present.
var ErrNoLocation = errors.New("http: no Location header in response")
Location returns the URL of the response's "Location" header, if present. Relative redirects are resolved relative to the Response's Request. ErrNoLocation is returned if no Location header is present.
func ( *Response) () (*url.URL, error) {
	 := .Header.Get("Location")
	if  == "" {
		return nil, ErrNoLocation
	}
	if .Request != nil && .Request.URL != nil {
		return .Request.URL.Parse()
	}
	return url.Parse()
}
ReadResponse reads and returns an HTTP response from r. The req parameter optionally specifies the Request that corresponds to this Response. If nil, a GET request is assumed. Clients must call resp.Body.Close when finished reading resp.Body. After that call, clients can inspect resp.Trailer to find key/value pairs included in the response trailer.
func ( *bufio.Reader,  *Request) (*Response, error) {
	 := textproto.NewReader()
	 := &Response{
		Request: ,
	}
Parse the first line of the response.
	,  := .ReadLine()
	if  != nil {
		if  == io.EOF {
			 = io.ErrUnexpectedEOF
		}
		return nil, 
	}
	if  := strings.IndexByte(, ' ');  == -1 {
		return nil, badStringError("malformed HTTP response", )
	} else {
		.Proto = [:]
		.Status = strings.TrimLeft([+1:], " ")
	}
	 := .Status
	if  := strings.IndexByte(.Status, ' ');  != -1 {
		 = .Status[:]
	}
	if len() != 3 {
		return nil, badStringError("malformed HTTP status code", )
	}
	.StatusCode,  = strconv.Atoi()
	if  != nil || .StatusCode < 0 {
		return nil, badStringError("malformed HTTP status code", )
	}
	var  bool
	if .ProtoMajor, .ProtoMinor,  = ParseHTTPVersion(.Proto); ! {
		return nil, badStringError("malformed HTTP version", .Proto)
	}
Parse the response headers.
	,  := .ReadMIMEHeader()
	if  != nil {
		if  == io.EOF {
			 = io.ErrUnexpectedEOF
		}
		return nil, 
	}
	.Header = Header()

	fixPragmaCacheControl(.Header)

	 = readTransfer(, )
	if  != nil {
		return nil, 
	}

	return , nil
}
RFC 7234, section 5.4: Should treat Pragma: no-cache like Cache-Control: no-cache
func ( Header) {
	if ,  := ["Pragma"];  && len() > 0 && [0] == "no-cache" {
		if ,  := ["Cache-Control"]; ! {
			["Cache-Control"] = []string{"no-cache"}
		}
	}
}
ProtoAtLeast reports whether the HTTP protocol used in the response is at least major.minor.
func ( *Response) (,  int) bool {
	return .ProtoMajor >  ||
		.ProtoMajor ==  && .ProtoMinor >= 
}
Write writes r to w in the HTTP/1.x server response format, including the status line, headers, body, and optional trailer. This method consults the following fields of the response r: StatusCode ProtoMajor ProtoMinor Request.Method TransferEncoding Trailer Body ContentLength Header, values for non-canonical keys will have unpredictable behavior The Response Body is closed after it is sent.
Status line
	 := .Status
	if  == "" {
		var  bool
		,  = statusText[.StatusCode]
		if ! {
			 = "status code " + strconv.Itoa(.StatusCode)
		}
Just to reduce stutter, if user set r.Status to "200 OK" and StatusCode to 200. Not important.
		 = strings.TrimPrefix(, strconv.Itoa(.StatusCode)+" ")
	}

	if ,  := fmt.Fprintf(, "HTTP/%d.%d %03d %s\r\n", .ProtoMajor, .ProtoMinor, .StatusCode, );  != nil {
		return 
	}
Clone it, so we can modify r1 as needed.
	 := new(Response)
	* = *
Is it actually 0 length? Or just unknown?
		var  [1]byte
		,  := .Body.Read([:])
		if  != nil &&  != io.EOF {
			return 
		}
Reset it to a known zero reader, in case underlying one is unhappy being read repeatedly.
			.Body = NoBody
		} else {
			.ContentLength = -1
			.Body = struct {
				io.Reader
				io.Closer
			}{
				io.MultiReader(bytes.NewReader([:1]), .Body),
				.Body,
			}
		}
If we're sending a non-chunked HTTP/1.1 response without a content-length, the only way to do that is the old HTTP/1.0 way, by noting the EOF with a connection close, so we need to set Close.
	if .ContentLength == -1 && !.Close && .ProtoAtLeast(1, 1) && !chunked(.TransferEncoding) && !.Uncompressed {
		.Close = true
	}
Process Body,ContentLength,Close,Trailer
	,  := newTransferWriter()
	if  != nil {
		return 
	}
	 = .writeHeader(, nil)
	if  != nil {
		return 
	}
Rest of header
	 = .Header.WriteSubset(, respExcludeHeader)
	if  != nil {
		return 
	}
contentLengthAlreadySent may have been already sent for POST/PUT requests, even if zero length. See Issue 8180.
	 := .shouldSendContentLength()
	if .ContentLength == 0 && !chunked(.TransferEncoding) && ! && bodyAllowedForStatus(.StatusCode) {
		if ,  := io.WriteString(, "Content-Length: 0\r\n");  != nil {
			return 
		}
	}
End-of-header
	if ,  := io.WriteString(, "\r\n");  != nil {
		return 
	}
Write body and trailer
	 = .writeBody()
	if  != nil {
		return 
	}
Success
	return nil
}

func ( *Response) () {
	if .Body != nil {
		.Body.Close()
	}
}
bodyIsWritable reports whether the Body supports writing. The Transport returns Writable bodies for 101 Switching Protocols responses. The Transport uses this method to determine whether a persistent connection is done being managed from its perspective. Once we return a writable response body to a user, the net/http package is done managing that connection.
func ( *Response) () bool {
	,  := .Body.(io.Writer)
	return 
}
isProtocolSwitch reports whether the response code and header indicate a successful protocol upgrade response.
isProtocolSwitchResponse reports whether the response code and response header indicate a successful protocol upgrade response.
isProtocolSwitchHeader reports whether the request or response header is for a protocol switch.
func ( Header) bool {
	return .Get("Upgrade") != "" &&
		httpguts.HeaderValuesContainsToken(["Connection"], "Upgrade")