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
7package http
8
9import (
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
24var 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.
35type 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.
125func (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.
131var 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.
137func (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.
154func 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
214func 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.
224func (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.
245func (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
337func (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.
350func (r *Response) bodyIsWritable() bool {
351	_, ok := r.Body.(io.Writer)
352	return ok
353}
354
355// isProtocolSwitch reports whether r is a response to a successful
356// protocol upgrade.
357func (r *Response) isProtocolSwitch() bool {
358	return r.StatusCode == StatusSwitchingProtocols &&
359		r.Header.Get("Upgrade") != "" &&
360		httpguts.HeaderValuesContainsToken(r.Header["Connection"], "Upgrade")
361}
362