github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/net/http/response.go (about) 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 "internal/x/net/http/httpguts" 16 "io" 17 "net/textproto" 18 "net/url" 19 "strconv" 20 "strings" 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 string // e.g. "200 OK" 36 StatusCode int // e.g. 200 37 Proto string // 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 be also implement io.Writer 69 // on a successful "101 Switching Protocols" responses, 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 []string 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 Response's 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 // the Response's 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 if i := strings.IndexByte(line, ' '); i == -1 { 168 return nil, &badStringError{"malformed HTTP response", line} 169 } else { 170 resp.Proto = line[:i] 171 resp.Status = strings.TrimLeft(line[i+1:], " ") 172 } 173 statusCode := resp.Status 174 if i := strings.IndexByte(resp.Status, ' '); i != -1 { 175 statusCode = resp.Status[:i] 176 } 177 if len(statusCode) != 3 { 178 return nil, &badStringError{"malformed HTTP status code", statusCode} 179 } 180 resp.StatusCode, err = strconv.Atoi(statusCode) 181 if err != nil || resp.StatusCode < 0 { 182 return nil, &badStringError{"malformed HTTP status code", statusCode} 183 } 184 var ok bool 185 if resp.ProtoMajor, resp.ProtoMinor, ok = ParseHTTPVersion(resp.Proto); !ok { 186 return nil, &badStringError{"malformed HTTP version", resp.Proto} 187 } 188 189 // Parse the response headers. 190 mimeHeader, err := tp.ReadMIMEHeader() 191 if err != nil { 192 if err == io.EOF { 193 err = io.ErrUnexpectedEOF 194 } 195 return nil, err 196 } 197 resp.Header = Header(mimeHeader) 198 199 fixPragmaCacheControl(resp.Header) 200 201 err = readTransfer(resp, r) 202 if err != nil { 203 return nil, err 204 } 205 206 return resp, nil 207 } 208 209 // RFC 7234, section 5.4: Should treat 210 // Pragma: no-cache 211 // like 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"] = []string{"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 var ok bool 249 text, ok = statusText[r.StatusCode] 250 if !ok { 251 text = "status code " + strconv.Itoa(r.StatusCode) 252 } 253 } else { 254 // Just to reduce stutter, if user set r.Status to "200 OK" and StatusCode to 200. 255 // Not important. 256 text = strings.TrimPrefix(text, strconv.Itoa(r.StatusCode)+" ") 257 } 258 259 if _, err := fmt.Fprintf(w, "HTTP/%d.%d %03d %s\r\n", r.ProtoMajor, r.ProtoMinor, r.StatusCode, text); err != nil { 260 return err 261 } 262 263 // Clone it, so we can modify r1 as needed. 264 r1 := new(Response) 265 *r1 = *r 266 if r1.ContentLength == 0 && r1.Body != nil { 267 // Is it actually 0 length? Or just unknown? 268 var buf [1]byte 269 n, err := r1.Body.Read(buf[:]) 270 if err != nil && err != io.EOF { 271 return err 272 } 273 if n == 0 { 274 // Reset it to a known zero reader, in case underlying one 275 // is unhappy being read repeatedly. 276 r1.Body = NoBody 277 } else { 278 r1.ContentLength = -1 279 r1.Body = struct { 280 io.Reader 281 io.Closer 282 }{ 283 io.MultiReader(bytes.NewReader(buf[:1]), r.Body), 284 r.Body, 285 } 286 } 287 } 288 // If we're sending a non-chunked HTTP/1.1 response without a 289 // content-length, the only way to do that is the old HTTP/1.0 290 // way, by noting the EOF with a connection close, so we need 291 // to set Close. 292 if r1.ContentLength == -1 && !r1.Close && r1.ProtoAtLeast(1, 1) && !chunked(r1.TransferEncoding) && !r1.Uncompressed { 293 r1.Close = true 294 } 295 296 // Process Body,ContentLength,Close,Trailer 297 tw, err := newTransferWriter(r1) 298 if err != nil { 299 return err 300 } 301 err = tw.writeHeader(w, nil) 302 if err != nil { 303 return err 304 } 305 306 // Rest of header 307 err = r.Header.WriteSubset(w, respExcludeHeader) 308 if err != nil { 309 return err 310 } 311 312 // contentLengthAlreadySent may have been already sent for 313 // POST/PUT requests, even if zero length. See Issue 8180. 314 contentLengthAlreadySent := tw.shouldSendContentLength() 315 if r1.ContentLength == 0 && !chunked(r1.TransferEncoding) && !contentLengthAlreadySent && bodyAllowedForStatus(r.StatusCode) { 316 if _, err := io.WriteString(w, "Content-Length: 0\r\n"); err != nil { 317 return err 318 } 319 } 320 321 // End-of-header 322 if _, err := io.WriteString(w, "\r\n"); err != nil { 323 return err 324 } 325 326 // Write body and trailer 327 err = tw.writeBody(w) 328 if err != nil { 329 return err 330 } 331 332 // Success 333 return nil 334 } 335 336 func (r *Response) closeBody() { 337 if r.Body != nil { 338 r.Body.Close() 339 } 340 } 341 342 // bodyIsWritable reports whether the Body supports writing. The 343 // Transport returns Writable bodies for 101 Switching Protocols 344 // responses. 345 // The Transport uses this method to determine whether a persistent 346 // connection is done being managed from its perspective. Once we 347 // return a writable response body to a user, the net/http package is 348 // done managing that connection. 349 func (r *Response) bodyIsWritable() bool { 350 _, ok := r.Body.(io.Writer) 351 return ok 352 } 353 354 // isProtocolSwitch reports whether r is a response to a successful 355 // protocol upgrade. 356 func (r *Response) isProtocolSwitch() bool { 357 return r.StatusCode == StatusSwitchingProtocols && 358 r.Header.Get("Upgrade") != "" && 359 httpguts.HeaderValuesContainsToken(r.Header["Connection"], "Upgrade") 360 }