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