mirror of
https://github.com/golang/go
synced 2024-11-23 19:00:04 -07:00
net/http: remove badStringError, make some unexported structs non-comparable
Reduces binary size by 4K, not counting the http2 changes (in CL 231119) that'll be bundled into this package in the future. Updates golang/go#38782 Change-Id: Id360348707e076b8310a8f409e412d68dd2394b2 Reviewed-on: https://go-review.googlesource.com/c/go/+/231118 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
e1d16843bd
commit
b8fd3cab39
@ -16,6 +16,11 @@ import (
|
|||||||
"golang.org/x/net/http/httpguts"
|
"golang.org/x/net/http/httpguts"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// incomparable is a zero-width, non-comparable type. Adding it to a struct
|
||||||
|
// makes that struct also non-comparable, and generally doesn't add
|
||||||
|
// any size (as long as it's first).
|
||||||
|
type incomparable [0]func()
|
||||||
|
|
||||||
// maxInt64 is the effective "infinite" value for the Server and
|
// maxInt64 is the effective "infinite" value for the Server and
|
||||||
// Transport's byte-limiting readers.
|
// Transport's byte-limiting readers.
|
||||||
const maxInt64 = 1<<63 - 1
|
const maxInt64 = 1<<63 - 1
|
||||||
|
@ -35,7 +35,7 @@ func TestCacheKeys(t *testing.T) {
|
|||||||
}
|
}
|
||||||
proxy = u
|
proxy = u
|
||||||
}
|
}
|
||||||
cm := connectMethod{proxy, tt.scheme, tt.addr, false}
|
cm := connectMethod{proxyURL: proxy, targetScheme: tt.scheme, targetAddr: tt.addr}
|
||||||
if got := cm.key().String(); got != tt.key {
|
if got := cm.key().String(); got != tt.key {
|
||||||
t.Fatalf("{%q, %q, %q} cache key = %q; want %q", tt.proxy, tt.scheme, tt.addr, got, tt.key)
|
t.Fatalf("{%q, %q, %q} cache key = %q; want %q", tt.proxy, tt.scheme, tt.addr, got, tt.key)
|
||||||
}
|
}
|
||||||
|
@ -83,12 +83,7 @@ var (
|
|||||||
ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"}
|
ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"}
|
||||||
)
|
)
|
||||||
|
|
||||||
type badStringError struct {
|
func badStringError(what, val string) error { return fmt.Errorf("%s %q", what, val) }
|
||||||
what string
|
|
||||||
str string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }
|
|
||||||
|
|
||||||
// Headers that Request.Write handles itself and should be skipped.
|
// Headers that Request.Write handles itself and should be skipped.
|
||||||
var reqWriteExcludeHeader = map[string]bool{
|
var reqWriteExcludeHeader = map[string]bool{
|
||||||
@ -1025,14 +1020,14 @@ func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err erro
|
|||||||
var ok bool
|
var ok bool
|
||||||
req.Method, req.RequestURI, req.Proto, ok = parseRequestLine(s)
|
req.Method, req.RequestURI, req.Proto, ok = parseRequestLine(s)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, &badStringError{"malformed HTTP request", s}
|
return nil, badStringError("malformed HTTP request", s)
|
||||||
}
|
}
|
||||||
if !validMethod(req.Method) {
|
if !validMethod(req.Method) {
|
||||||
return nil, &badStringError{"invalid method", req.Method}
|
return nil, badStringError("invalid method", req.Method)
|
||||||
}
|
}
|
||||||
rawurl := req.RequestURI
|
rawurl := req.RequestURI
|
||||||
if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
|
if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
|
||||||
return nil, &badStringError{"malformed HTTP version", req.Proto}
|
return nil, badStringError("malformed HTTP version", req.Proto)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CONNECT requests are used two different ways, and neither uses a full URL:
|
// CONNECT requests are used two different ways, and neither uses a full URL:
|
||||||
|
@ -166,7 +166,7 @@ func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if i := strings.IndexByte(line, ' '); i == -1 {
|
if i := strings.IndexByte(line, ' '); i == -1 {
|
||||||
return nil, &badStringError{"malformed HTTP response", line}
|
return nil, badStringError("malformed HTTP response", line)
|
||||||
} else {
|
} else {
|
||||||
resp.Proto = line[:i]
|
resp.Proto = line[:i]
|
||||||
resp.Status = strings.TrimLeft(line[i+1:], " ")
|
resp.Status = strings.TrimLeft(line[i+1:], " ")
|
||||||
@ -176,15 +176,15 @@ func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) {
|
|||||||
statusCode = resp.Status[:i]
|
statusCode = resp.Status[:i]
|
||||||
}
|
}
|
||||||
if len(statusCode) != 3 {
|
if len(statusCode) != 3 {
|
||||||
return nil, &badStringError{"malformed HTTP status code", statusCode}
|
return nil, badStringError("malformed HTTP status code", statusCode)
|
||||||
}
|
}
|
||||||
resp.StatusCode, err = strconv.Atoi(statusCode)
|
resp.StatusCode, err = strconv.Atoi(statusCode)
|
||||||
if err != nil || resp.StatusCode < 0 {
|
if err != nil || resp.StatusCode < 0 {
|
||||||
return nil, &badStringError{"malformed HTTP status code", statusCode}
|
return nil, badStringError("malformed HTTP status code", statusCode)
|
||||||
}
|
}
|
||||||
var ok bool
|
var ok bool
|
||||||
if resp.ProtoMajor, resp.ProtoMinor, ok = ParseHTTPVersion(resp.Proto); !ok {
|
if resp.ProtoMajor, resp.ProtoMinor, ok = ParseHTTPVersion(resp.Proto); !ok {
|
||||||
return nil, &badStringError{"malformed HTTP version", resp.Proto}
|
return nil, badStringError("malformed HTTP version", resp.Proto)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the response headers.
|
// Parse the response headers.
|
||||||
|
@ -629,6 +629,7 @@ func (srv *Server) newConn(rwc net.Conn) *conn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type readResult struct {
|
type readResult struct {
|
||||||
|
_ incomparable
|
||||||
n int
|
n int
|
||||||
err error
|
err error
|
||||||
b byte // byte read, if n == 1
|
b byte // byte read, if n == 1
|
||||||
|
@ -310,7 +310,7 @@ func (t *transferWriter) writeHeader(w io.Writer, trace *httptrace.ClientTrace)
|
|||||||
k = CanonicalHeaderKey(k)
|
k = CanonicalHeaderKey(k)
|
||||||
switch k {
|
switch k {
|
||||||
case "Transfer-Encoding", "Trailer", "Content-Length":
|
case "Transfer-Encoding", "Trailer", "Content-Length":
|
||||||
return &badStringError{"invalid Trailer key", k}
|
return badStringError("invalid Trailer key", k)
|
||||||
}
|
}
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
}
|
}
|
||||||
@ -637,7 +637,7 @@ func (t *transferReader) fixTransferEncoding() error {
|
|||||||
te[len(te)-1] = encoding
|
te[len(te)-1] = encoding
|
||||||
}
|
}
|
||||||
if len(te) > 1 {
|
if len(te) > 1 {
|
||||||
return &badStringError{"too many transfer encodings", strings.Join(te, ",")}
|
return badStringError("too many transfer encodings", strings.Join(te, ","))
|
||||||
}
|
}
|
||||||
if len(te) > 0 {
|
if len(te) > 0 {
|
||||||
// RFC 7230 3.3.2 says "A sender MUST NOT send a
|
// RFC 7230 3.3.2 says "A sender MUST NOT send a
|
||||||
@ -791,7 +791,7 @@ func fixTrailer(header Header, te []string) (Header, error) {
|
|||||||
switch key {
|
switch key {
|
||||||
case "Transfer-Encoding", "Trailer", "Content-Length":
|
case "Transfer-Encoding", "Trailer", "Content-Length":
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = &badStringError{"bad trailer key", key}
|
err = badStringError("bad trailer key", key)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1055,7 +1055,7 @@ func parseContentLength(cl string) (int64, error) {
|
|||||||
}
|
}
|
||||||
n, err := strconv.ParseInt(cl, 10, 64)
|
n, err := strconv.ParseInt(cl, 10, 64)
|
||||||
if err != nil || n < 0 {
|
if err != nil || n < 0 {
|
||||||
return 0, &badStringError{"bad Content-Length", cl}
|
return 0, badStringError("bad Content-Length", cl)
|
||||||
}
|
}
|
||||||
return n, nil
|
return n, nil
|
||||||
|
|
||||||
|
@ -290,7 +290,7 @@ func TestFixTransferEncoding(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
hdr: Header{"Transfer-Encoding": {"chunked, chunked", "identity", "chunked"}},
|
hdr: Header{"Transfer-Encoding": {"chunked, chunked", "identity", "chunked"}},
|
||||||
wantErr: &badStringError{"too many transfer encodings", "chunked,chunked"},
|
wantErr: badStringError("too many transfer encodings", "chunked,chunked"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hdr: Header{"Transfer-Encoding": {"chunked"}},
|
hdr: Header{"Transfer-Encoding": {"chunked"}},
|
||||||
|
@ -518,7 +518,7 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) {
|
|||||||
}
|
}
|
||||||
if !isHTTP {
|
if !isHTTP {
|
||||||
req.closeBody()
|
req.closeBody()
|
||||||
return nil, &badStringError{"unsupported protocol scheme", scheme}
|
return nil, badStringError("unsupported protocol scheme", scheme)
|
||||||
}
|
}
|
||||||
if req.Method != "" && !validMethod(req.Method) {
|
if req.Method != "" && !validMethod(req.Method) {
|
||||||
req.closeBody()
|
req.closeBody()
|
||||||
@ -1696,6 +1696,7 @@ var _ io.ReaderFrom = (*persistConnWriter)(nil)
|
|||||||
// https://proxy.com|http https to proxy, http to anywhere after that
|
// https://proxy.com|http https to proxy, http to anywhere after that
|
||||||
//
|
//
|
||||||
type connectMethod struct {
|
type connectMethod struct {
|
||||||
|
_ incomparable
|
||||||
proxyURL *url.URL // nil for no proxy, else full proxy URL
|
proxyURL *url.URL // nil for no proxy, else full proxy URL
|
||||||
targetScheme string // "http" or "https"
|
targetScheme string // "http" or "https"
|
||||||
// If proxyURL specifies an http or https proxy, and targetScheme is http (not https),
|
// If proxyURL specifies an http or https proxy, and targetScheme is http (not https),
|
||||||
@ -2250,6 +2251,7 @@ func newReadWriteCloserBody(br *bufio.Reader, rwc io.ReadWriteCloser) io.ReadWri
|
|||||||
// the concrete type for a Response.Body on the 101 Switching
|
// the concrete type for a Response.Body on the 101 Switching
|
||||||
// Protocols response, as used by WebSockets, h2c, etc.
|
// Protocols response, as used by WebSockets, h2c, etc.
|
||||||
type readWriteCloserBody struct {
|
type readWriteCloserBody struct {
|
||||||
|
_ incomparable
|
||||||
br *bufio.Reader // used until empty
|
br *bufio.Reader // used until empty
|
||||||
io.ReadWriteCloser
|
io.ReadWriteCloser
|
||||||
}
|
}
|
||||||
@ -2350,11 +2352,13 @@ func (pc *persistConn) wroteRequest() bool {
|
|||||||
// responseAndError is how the goroutine reading from an HTTP/1 server
|
// responseAndError is how the goroutine reading from an HTTP/1 server
|
||||||
// communicates with the goroutine doing the RoundTrip.
|
// communicates with the goroutine doing the RoundTrip.
|
||||||
type responseAndError struct {
|
type responseAndError struct {
|
||||||
|
_ incomparable
|
||||||
res *Response // else use this response (see res method)
|
res *Response // else use this response (see res method)
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
type requestAndChan struct {
|
type requestAndChan struct {
|
||||||
|
_ incomparable
|
||||||
req *Request
|
req *Request
|
||||||
ch chan responseAndError // unbuffered; always send in select on callerGone
|
ch chan responseAndError // unbuffered; always send in select on callerGone
|
||||||
|
|
||||||
@ -2687,6 +2691,7 @@ func (es *bodyEOFSignal) condfn(err error) error {
|
|||||||
// gzipReader wraps a response body so it can lazily
|
// gzipReader wraps a response body so it can lazily
|
||||||
// call gzip.NewReader on the first call to Read
|
// call gzip.NewReader on the first call to Read
|
||||||
type gzipReader struct {
|
type gzipReader struct {
|
||||||
|
_ incomparable
|
||||||
body *bodyEOFSignal // underlying HTTP/1 response body framing
|
body *bodyEOFSignal // underlying HTTP/1 response body framing
|
||||||
zr *gzip.Reader // lazily-initialized gzip reader
|
zr *gzip.Reader // lazily-initialized gzip reader
|
||||||
zerr error // any error from gzip.NewReader; sticky
|
zerr error // any error from gzip.NewReader; sticky
|
||||||
|
Loading…
Reference in New Issue
Block a user