1
0
mirror of https://github.com/golang/go synced 2024-10-02 10:18:33 -06:00

net/http: use RFC 723x as normative reference in docs

Replace references to the obsoleted RFC 2616 with references to RFC
7230 through 7235, to avoid unnecessary confusion.
Obvious inconsistencies are marked with todo comments.

Updates #21974

Change-Id: I8fb4fcdd1333fc5193b93a2f09598f18c45e7a00
Reviewed-on: https://go-review.googlesource.com/94095
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
David Url 2018-02-13 22:03:05 +01:00 committed by Brad Fitzpatrick
parent 4313d7767d
commit 7662e6588c
12 changed files with 56 additions and 62 deletions

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// HTTP client. See RFC 2616. // HTTP client. See RFC 7230 through 7235.
// //
// This is the high-level Client interface. // This is the high-level Client interface.
// The low-level implementation is in transport.go. // The low-level implementation is in transport.go.

View File

@ -235,17 +235,17 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
} }
switch { switch {
case len(ranges) == 1: case len(ranges) == 1:
// RFC 2616, Section 14.16: // RFC 7233, Section 4.1:
// "When an HTTP message includes the content of a single // "If a single part is being transferred, the server
// range (for example, a response to a request for a // generating the 206 response MUST generate a
// single range, or to a request for a set of ranges // Content-Range header field, describing what range
// that overlap without any holes), this content is // of the selected representation is enclosed, and a
// transmitted with a Content-Range header, and a // payload consisting of the range.
// Content-Length header showing the number of bytes
// actually transferred.
// ... // ...
// A response to a request for a single range MUST NOT // A server MUST NOT generate a multipart response to
// be sent using the multipart/byteranges media type." // a request for a single range, since a client that
// does not request multiple parts might not support
// multipart responses."
ra := ranges[0] ra := ranges[0]
if _, err := content.Seek(ra.start, io.SeekStart); err != nil { if _, err := content.Seek(ra.start, io.SeekStart); err != nil {
Error(w, err.Error(), StatusRequestedRangeNotSatisfiable) Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
@ -731,7 +731,7 @@ func (r httpRange) mimeHeader(contentType string, size int64) textproto.MIMEHead
} }
} }
// parseRange parses a Range header string as per RFC 2616. // parseRange parses a Range header string as per RFC 7233.
// errNoOverlap is returned if none of the ranges overlap. // errNoOverlap is returned if none of the ranges overlap.
func parseRange(s string, size int64) ([]httpRange, error) { func parseRange(s string, size int64) ([]httpRange, error) {
if s == "" { if s == "" {

View File

@ -192,6 +192,7 @@ func (rw *ResponseRecorder) Result() *http.Response {
switch k { switch k {
case "Transfer-Encoding", "Content-Length", "Trailer": case "Transfer-Encoding", "Content-Length", "Trailer":
// Ignore since forbidden by RFC 2616 14.40. // Ignore since forbidden by RFC 2616 14.40.
// TODO: inconsistent with RFC 7230, section 4.1.2.
continue continue
} }
k = http.CanonicalHeaderKey(k) k = http.CanonicalHeaderKey(k)

View File

@ -125,7 +125,10 @@ func cloneHeader(h http.Header) http.Header {
} }
// Hop-by-hop headers. These are removed when sent to the backend. // Hop-by-hop headers. These are removed when sent to the backend.
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html // As of RFC 7230, hop-by-hop headers are required to appear in the
// Connection header field. These are the headers defined by the
// obsoleted RFC 2616 (section 13.5.1) and are used for backward
// compatibility.
var hopHeaders = []string{ var hopHeaders = []string{
"Connection", "Connection",
"Proxy-Connection", // non-standard but still sent by libcurl and rejected by e.g. google "Proxy-Connection", // non-standard but still sent by libcurl and rejected by e.g. google
@ -251,7 +254,7 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
} }
// removeConnectionHeaders removes hop-by-hop headers listed in the "Connection" header of h. // removeConnectionHeaders removes hop-by-hop headers listed in the "Connection" header of h.
// See RFC 2616, section 14.10. // See RFC 7230, section 6.1
func removeConnectionHeaders(h http.Header) { func removeConnectionHeaders(h http.Header) {
if c := h.Get("Connection"); c != "" { if c := h.Get("Connection"); c != "" {
for _, f := range strings.Split(c, ",") { for _, f := range strings.Split(c, ",") {

View File

@ -126,7 +126,7 @@ var reqTests = []reqTest{
noError, noError,
}, },
// Tests a bogus abs_path on the Request-Line (RFC 2616 section 5.1.2) // Tests a bogus absolute-path on the Request-Line (RFC 7230 section 5.3.1)
{ {
"GET ../../../../etc/passwd HTTP/1.1\r\n" + "GET ../../../../etc/passwd HTTP/1.1\r\n" +
"Host: test\r\n\r\n", "Host: test\r\n\r\n",

View File

@ -110,7 +110,7 @@ type Request struct {
// For server requests the URL is parsed from the URI // For server requests the URL is parsed from the URI
// supplied on the Request-Line as stored in RequestURI. For // supplied on the Request-Line as stored in RequestURI. For
// most requests, fields other than Path and RawQuery will be // most requests, fields other than Path and RawQuery will be
// empty. (See RFC 2616, Section 5.1.2) // empty. (See RFC 7230, Section 5.3)
// //
// For client requests, the URL's Host specifies the server to // For client requests, the URL's Host specifies the server to
// connect to, while the Request's Host field optionally // connect to, while the Request's Host field optionally
@ -207,9 +207,9 @@ type Request struct {
// Transport.DisableKeepAlives were set. // Transport.DisableKeepAlives were set.
Close bool Close bool
// For server requests Host specifies the host on which the // For server requests Host specifies the host on which the URL
// URL is sought. Per RFC 2616, this is either the value of // is sought. Per RFC 7230, section 5.4, this is either the value
// the "Host" header or the host name given in the URL itself. // of the "Host" header or the host name given in the URL itself.
// It may be of the form "host:port". For international domain // It may be of the form "host:port". For international domain
// names, Host may be in Punycode or Unicode form. Use // names, Host may be in Punycode or Unicode form. Use
// golang.org/x/net/idna to convert it to either format if // golang.org/x/net/idna to convert it to either format if
@ -268,8 +268,8 @@ type Request struct {
// This field is ignored by the HTTP client. // This field is ignored by the HTTP client.
RemoteAddr string RemoteAddr string
// RequestURI is the unmodified Request-URI of the // RequestURI is the unmodified request-target of the
// Request-Line (RFC 2616, Section 5.1) as sent by the client // Request-Line (RFC 7230, Section 3.1.1) as sent by the client
// to a server. Usually the URL field should be used instead. // to a server. Usually the URL field should be used instead.
// It is an error to set this field in an HTTP client request. // It is an error to set this field in an HTTP client request.
RequestURI string RequestURI string
@ -481,7 +481,7 @@ func (r *Request) Write(w io.Writer) error {
// WriteProxy is like Write but writes the request in the form // WriteProxy is like Write but writes the request in the form
// expected by an HTTP proxy. In particular, WriteProxy writes the // expected by an HTTP proxy. In particular, WriteProxy writes the
// initial Request-URI line of the request with an absolute URI, per // initial Request-URI line of the request with an absolute URI, per
// section 5.1.2 of RFC 2616, including the scheme and host. // section 5.3 of RFC 7230, including the scheme and host.
// In either case, WriteProxy also writes a Host header, using // In either case, WriteProxy also writes a Host header, using
// either r.Host or r.URL.Host. // either r.Host or r.URL.Host.
func (r *Request) WriteProxy(w io.Writer) error { func (r *Request) WriteProxy(w io.Writer) error {
@ -979,7 +979,7 @@ func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err erro
} }
req.Header = Header(mimeHeader) req.Header = Header(mimeHeader)
// RFC 2616: Must treat // RFC 7230, section 5.3: Must treat
// GET /index.html HTTP/1.1 // GET /index.html HTTP/1.1
// Host: www.google.com // Host: www.google.com
// and // and
@ -1094,8 +1094,8 @@ func parsePostForm(r *Request) (vs url.Values, err error) {
return return
} }
ct := r.Header.Get("Content-Type") ct := r.Header.Get("Content-Type")
// RFC 2616, section 7.2.1 - empty type // RFC 7231, section 3.1.1.5 - empty type
// SHOULD be treated as application/octet-stream // MAY be treated as application/octet-stream
if ct == "" { if ct == "" {
ct = "application/octet-stream" ct = "application/octet-stream"
} }

View File

@ -91,8 +91,8 @@ type parseContentTypeTest struct {
var parseContentTypeTests = []parseContentTypeTest{ var parseContentTypeTests = []parseContentTypeTest{
{false, stringMap{"Content-Type": {"text/plain"}}}, {false, stringMap{"Content-Type": {"text/plain"}}},
// Empty content type is legal - should be treated as // Empty content type is legal - may be treated as
// application/octet-stream (RFC 2616, section 7.2.1) // application/octet-stream (RFC 7231, section 3.1.1.5)
{false, stringMap{}}, {false, stringMap{}},
{true, stringMap{"Content-Type": {"text/plain; boundary="}}}, {true, stringMap{"Content-Type": {"text/plain; boundary="}}},
{false, stringMap{"Content-Type": {"application/unknown"}}}, {false, stringMap{"Content-Type": {"application/unknown"}}},

View File

@ -39,7 +39,7 @@ type Response struct {
// Header maps header keys to values. If the response had multiple // Header maps header keys to values. If the response had multiple
// headers with the same key, they may be concatenated, with comma // headers with the same key, they may be concatenated, with comma
// delimiters. (Section 4.2 of RFC 2616 requires that multiple headers // delimiters. (RFC 7230, section 3.2.2 requires that multiple headers
// be semantically equivalent to a comma-delimited sequence.) When // be semantically equivalent to a comma-delimited sequence.) When
// Header values are duplicated by other fields in this struct (e.g., // Header values are duplicated by other fields in this struct (e.g.,
// ContentLength, TransferEncoding, Trailer), the field values are // ContentLength, TransferEncoding, Trailer), the field values are
@ -201,7 +201,7 @@ func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) {
return resp, nil return resp, nil
} }
// RFC 2616: Should treat // RFC 7234, section 5.4: Should treat
// Pragma: no-cache // Pragma: no-cache
// like // like
// Cache-Control: no-cache // Cache-Control: no-cache

View File

@ -295,7 +295,7 @@ var respTests = []respTest{
}, },
// Status line without a Reason-Phrase, but trailing space. // Status line without a Reason-Phrase, but trailing space.
// (permitted by RFC 2616) // (permitted by RFC 7230, section 3.1.2)
{ {
"HTTP/1.0 303 \r\n\r\n", "HTTP/1.0 303 \r\n\r\n",
Response{ Response{
@ -314,7 +314,7 @@ var respTests = []respTest{
}, },
// Status line without a Reason-Phrase, and no trailing space. // Status line without a Reason-Phrase, and no trailing space.
// (not permitted by RFC 2616, but we'll accept it anyway) // (not permitted by RFC 7230, but we'll accept it anyway)
{ {
"HTTP/1.0 303\r\n\r\n", "HTTP/1.0 303\r\n\r\n",
Response{ Response{

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// HTTP server. See RFC 2616. // HTTP server. See RFC 7230 through 7235.
package http package http
@ -513,6 +513,7 @@ func (w *response) declareTrailer(k string) {
switch k { switch k {
case "Transfer-Encoding", "Content-Length", "Trailer": case "Transfer-Encoding", "Content-Length", "Trailer":
// Forbidden by RFC 2616 14.40. // Forbidden by RFC 2616 14.40.
// TODO: inconsistent with RFC 7230, section 4.1.2
return return
} }
w.trailers = append(w.trailers, k) w.trailers = append(w.trailers, k)
@ -937,7 +938,7 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
c.r.setReadLimit(c.server.initialReadLimitSize()) c.r.setReadLimit(c.server.initialReadLimitSize())
if c.lastMethod == "POST" { if c.lastMethod == "POST" {
// RFC 2616 section 4.1 tolerance for old buggy clients. // RFC 7230 section 3 tolerance for old buggy clients.
peek, _ := c.bufr.Peek(4) // ReadRequest will get err below peek, _ := c.bufr.Peek(4) // ReadRequest will get err below
c.bufr.Discard(numLeadingCRorLF(peek)) c.bufr.Discard(numLeadingCRorLF(peek))
} }
@ -1414,7 +1415,7 @@ func (cw *chunkWriter) writeHeader(p []byte) {
} }
// foreachHeaderElement splits v according to the "#rule" construction // foreachHeaderElement splits v according to the "#rule" construction
// in RFC 2616 section 2.1 and calls fn for each non-empty element. // in RFC 7230 section 7 and calls fn for each non-empty element.
func foreachHeaderElement(v string, fn func(string)) { func foreachHeaderElement(v string, fn func(string)) {
v = textproto.TrimString(v) v = textproto.TrimString(v)
if v == "" { if v == "" {
@ -1431,7 +1432,7 @@ func foreachHeaderElement(v string, fn func(string)) {
} }
} }
// writeStatusLine writes an HTTP/1.x Status-Line (RFC 2616 Section 6.1) // writeStatusLine writes an HTTP/1.x Status-Line (RFC 7230 Section 3.1.2)
// to bw. is11 is whether the HTTP request is HTTP/1.1. false means HTTP/1.0. // to bw. is11 is whether the HTTP request is HTTP/1.1. false means HTTP/1.0.
// code is the response status code. // code is the response status code.
// scratch is an optional scratch buffer. If it has at least capacity 3, it's used. // scratch is an optional scratch buffer. If it has at least capacity 3, it's used.
@ -1868,11 +1869,11 @@ func (w *response) sendExpectationFailed() {
// make the ResponseWriter an optional // make the ResponseWriter an optional
// "ExpectReplier" interface or something. // "ExpectReplier" interface or something.
// //
// For now we'll just obey RFC 2616 14.20 which says // For now we'll just obey RFC 7231 5.1.1 which says
// "If a server receives a request containing an // "A server that receives an Expect field-value other
// Expect field that includes an expectation- // than 100-continue MAY respond with a 417 (Expectation
// extension that it does not support, it MUST // Failed) status code to indicate that the unexpected
// respond with a 417 (Expectation Failed) status." // expectation cannot be met."
w.Header().Set("Connection", "close") w.Header().Set("Connection", "close")
w.WriteHeader(StatusExpectationFailed) w.WriteHeader(StatusExpectationFailed)
w.finishRequest() w.finishRequest()
@ -1998,22 +1999,11 @@ func StripPrefix(prefix string, h Handler) Handler {
func Redirect(w ResponseWriter, r *Request, url string, code int) { func Redirect(w ResponseWriter, r *Request, url string, code int) {
// parseURL is just url.Parse (url is shadowed for godoc). // parseURL is just url.Parse (url is shadowed for godoc).
if u, err := parseURL(url); err == nil { if u, err := parseURL(url); err == nil {
// If url was relative, make absolute by // If url was relative, make its path absolute by
// combining with request path. // combining with request path.
// The browser would probably do this for us, // The client would probably do this for us,
// but doing it ourselves is more reliable. // but doing it ourselves is more reliable.
// See RFC 7231, section 7.1.2
// NOTE(rsc): RFC 2616 says that the Location
// line must be an absolute URI, like
// "http://www.google.com/redirect/",
// not a path like "/redirect/".
// Unfortunately, we don't know what to
// put in the host name section to get the
// client to connect to us again, so we can't
// know the right absolute URI to send back.
// Because of this problem, no one pays attention
// to the RFC; they all send back just a new path.
// So do we.
if u.Scheme == "" && u.Host == "" { if u.Scheme == "" && u.Host == "" {
oldpath := r.URL.Path oldpath := r.URL.Path
if oldpath == "" { // should not happen, but avoid a crash if it does if oldpath == "" { // should not happen, but avoid a crash if it does
@ -2048,8 +2038,8 @@ func Redirect(w ResponseWriter, r *Request, url string, code int) {
} }
w.WriteHeader(code) w.WriteHeader(code)
// RFC 2616 recommends that a short note "SHOULD" be included in the // RFC 7231 notes that a short hypertext note is usually included in
// response because older user agents may not understand 301/307. // the response because older user agents may not understand 301/307.
// Shouldn't send the response for POST or HEAD; that leaves GET. // Shouldn't send the response for POST or HEAD; that leaves GET.
if r.Method == "GET" { if r.Method == "GET" {
note := "<a href=\"" + htmlEscape(url) + "\">" + statusText[code] + "</a>.\n" note := "<a href=\"" + htmlEscape(url) + "\">" + statusText[code] + "</a>.\n"

View File

@ -390,7 +390,7 @@ func (t *transferReader) protoAtLeast(m, n int) bool {
} }
// bodyAllowedForStatus reports whether a given response status code // bodyAllowedForStatus reports whether a given response status code
// permits a body. See RFC 2616, section 4.4. // permits a body. See RFC 7230, section 3.3.
func bodyAllowedForStatus(status int) bool { func bodyAllowedForStatus(status int) bool {
switch { switch {
case status >= 100 && status <= 199: case status >= 100 && status <= 199:
@ -411,7 +411,7 @@ var (
func suppressedHeaders(status int) []string { func suppressedHeaders(status int) []string {
switch { switch {
case status == 304: case status == 304:
// RFC 2616 section 10.3.5: "the response MUST NOT include other entity-headers" // RFC 7232 section 4.1
return suppressedHeaders304 return suppressedHeaders304
case !bodyAllowedForStatus(status): case !bodyAllowedForStatus(status):
return suppressedHeadersNoBody return suppressedHeadersNoBody
@ -482,7 +482,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
// If there is no Content-Length or chunked Transfer-Encoding on a *Response // If there is no Content-Length or chunked Transfer-Encoding on a *Response
// and the status is not 1xx, 204 or 304, then the body is unbounded. // and the status is not 1xx, 204 or 304, then the body is unbounded.
// See RFC 2616, section 4.4. // See RFC 7230, section 3.3.
switch msg.(type) { switch msg.(type) {
case *Response: case *Response:
if realLength == -1 && if realLength == -1 &&
@ -601,7 +601,7 @@ func (t *transferReader) fixTransferEncoding() error {
return nil return nil
} }
// Determine the expected body length, using RFC 2616 Section 4.4. This // Determine the expected body length, using RFC 7230 Section 3.3. This
// function is not a method, because ultimately it should be shared by // function is not a method, because ultimately it should be shared by
// ReadResponse and ReadRequest. // ReadResponse and ReadRequest.
func fixLength(isResponse bool, status int, requestMethod string, header Header, te []string) (int64, error) { func fixLength(isResponse bool, status int, requestMethod string, header Header, te []string) (int64, error) {
@ -667,7 +667,7 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
header.Del("Content-Length") header.Del("Content-Length")
if isRequest { if isRequest {
// RFC 2616 neither explicitly permits nor forbids an // RFC 7230 neither explicitly permits nor forbids an
// entity-body on a GET request so we permit one if // entity-body on a GET request so we permit one if
// declared, but we default to 0 here (not -1 below) // declared, but we default to 0 here (not -1 below)
// if there's no mention of a body. // if there's no mention of a body.

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// HTTP client implementation. See RFC 2616. // HTTP client implementation. See RFC 7230 through 7235.
// //
// This is the low-level Transport implementation of RoundTripper. // This is the low-level Transport implementation of RoundTripper.
// The high-level interface is in client.go. // The high-level interface is in client.go.