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