// Determine the expected body length, using RFC 7230 Section 3.3. This
// function is not a method, because ultimately it should be shared by
// ReadResponse and ReadRequest.
Determine the expected body length, using RFC 7230 Section 3.3. This
function is not a method, because ultimately it should be shared by
ReadResponse and ReadRequest.
// Determine the expected body length using RFC 7230 Section 3 . 3 . This // function is not a method because ultimately it should be shared by // ReadResponse and ReadRequest .
func fixLength(isResponse bool, status int, requestMethod string, header http.Header, chunked bool) (int64, error) {
	isRequest := !isResponse
	contentLens := header["Content-Length"]
	if len(contentLens) > 1 {
		first := textproto.TrimString(contentLens[0])
		for _, ct := range contentLens[1:] {
			if first != textproto.TrimString(ct) {
				return 0, fmt.Errorf("http: message cannot contain multiple Content-Length headers; got %q", contentLens)
			}
		}
		header.Del("Content-Length")
		header.Add("Content-Length", first)
		contentLens = header["Content-Length"]
	}
	if noResponseBodyExpected(requestMethod) {
		if isRequest && len(contentLens) > 0 && !(len(contentLens) == 1 && contentLens[0] == "0") {
			return 0, fmt.Errorf("http: method cannot contain a Content-Length; got %q", contentLens)
		}
		return 0, nil
	}
	if status/100 == 1 {
		return 0, nil
	}
	switch status {
	case 204, 304:
		return 0, nil
	}
	if chunked {
		return -1, nil
	}
	var cl string
	if len(contentLens) == 1 {
		cl = textproto.TrimString(contentLens[0])
	}
	if cl != "" {
		n, err := parseContentLength(cl)
		if err != nil {
			return -1, err
		}
		return n, nil
	}
	header.Del("Content-Length")
	if isRequest {
		return 0, nil
	}
	return -1, nil
}
func fixLength ( isResponse bool , status int , requestMethod string , header http . Header , chunked bool ) ( int64 , error ) { isRequest := ! isResponse contentLens := header [ " " ] if len ( contentLens ) > 1 { first := textproto . TrimString ( contentLens [ 0 ] ) for _ , ct := range contentLens [ 1 : ] { if first != textproto . TrimString ( ct ) { return 0 , fmt . Errorf ( " " , contentLens ) } } header . Del ( " " ) header . Add ( " " , first ) contentLens = header [ " " ] } if noResponseBodyExpected ( requestMethod ) { if isRequest && len ( contentLens ) > 0 && ! ( len ( contentLens ) == 1 && contentLens [ 0 ] == " " ) { return 0 , fmt . Errorf ( " " , contentLens ) } return 0 , nil } if status / 100 == 1 { return 0 , nil } switch status { case 204 , 304 : return 0 , nil } if chunked { return - 1 , nil } var cl string if len ( contentLens ) == 1 { cl = textproto . TrimString ( contentLens [ 0 ] ) } if cl != " " { n , err := parseContentLength ( cl ) if err != nil { return - 1 , err } return n , nil } header . Del ( " " ) if isRequest { return 0 , nil } return - 1 , nil }
Determine the expected body length, using RFC 7230 Section 3.3.
Determine the expected body length using RFC 7230 Section 3 . 3 .
// Hardening against HTTP request smuggling // Per RFC 7230 Section 3.3.2, prevent multiple // Content-Length headers if they differ in value. // If there are dups of the value, remove the dups. // See Issue 16490. // deduplicate Content-Length // Logic based on response type or status // For HTTP requests, as part of hardening against request // smuggling (RFC 7230), don't allow a Content-Length header for // methods which don't permit bodies. As an exception, allow // exactly one Content-Length header if its value is "0". // Logic based on Transfer-Encoding // Logic based on Content-Length // RFC 7230 neither explicitly permits nor forbids an // entity-body on a GET request so we permit one if // declared, but we default to 0 here (not -1 below) // if there's no mention of a body. // Likewise, all other request methods are assumed to have // no body if neither Transfer-Encoding chunked nor a // Content-Length are set. // Body-EOF logic based on other methods (like closing, or chunked coding)