Skip to content

Commit b8fd3ca

Browse files
committed
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 #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>
1 parent e1d1684 commit b8fd3ca

File tree

8 files changed

+26
-20
lines changed

8 files changed

+26
-20
lines changed

src/net/http/http.go

+5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import (
1616
"golang.org/x/net/http/httpguts"
1717
)
1818

19+
// incomparable is a zero-width, non-comparable type. Adding it to a struct
20+
// makes that struct also non-comparable, and generally doesn't add
21+
// any size (as long as it's first).
22+
type incomparable [0]func()
23+
1924
// maxInt64 is the effective "infinite" value for the Server and
2025
// Transport's byte-limiting readers.
2126
const maxInt64 = 1<<63 - 1

src/net/http/proxy_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestCacheKeys(t *testing.T) {
3535
}
3636
proxy = u
3737
}
38-
cm := connectMethod{proxy, tt.scheme, tt.addr, false}
38+
cm := connectMethod{proxyURL: proxy, targetScheme: tt.scheme, targetAddr: tt.addr}
3939
if got := cm.key().String(); got != tt.key {
4040
t.Fatalf("{%q, %q, %q} cache key = %q; want %q", tt.proxy, tt.scheme, tt.addr, got, tt.key)
4141
}

src/net/http/request.go

+4-9
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,7 @@ var (
8383
ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"}
8484
)
8585

86-
type badStringError struct {
87-
what string
88-
str string
89-
}
90-
91-
func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }
86+
func badStringError(what, val string) error { return fmt.Errorf("%s %q", what, val) }
9287

9388
// Headers that Request.Write handles itself and should be skipped.
9489
var reqWriteExcludeHeader = map[string]bool{
@@ -1025,14 +1020,14 @@ func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err erro
10251020
var ok bool
10261021
req.Method, req.RequestURI, req.Proto, ok = parseRequestLine(s)
10271022
if !ok {
1028-
return nil, &badStringError{"malformed HTTP request", s}
1023+
return nil, badStringError("malformed HTTP request", s)
10291024
}
10301025
if !validMethod(req.Method) {
1031-
return nil, &badStringError{"invalid method", req.Method}
1026+
return nil, badStringError("invalid method", req.Method)
10321027
}
10331028
rawurl := req.RequestURI
10341029
if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
1035-
return nil, &badStringError{"malformed HTTP version", req.Proto}
1030+
return nil, badStringError("malformed HTTP version", req.Proto)
10361031
}
10371032

10381033
// CONNECT requests are used two different ways, and neither uses a full URL:

src/net/http/response.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) {
166166
return nil, err
167167
}
168168
if i := strings.IndexByte(line, ' '); i == -1 {
169-
return nil, &badStringError{"malformed HTTP response", line}
169+
return nil, badStringError("malformed HTTP response", line)
170170
} else {
171171
resp.Proto = line[:i]
172172
resp.Status = strings.TrimLeft(line[i+1:], " ")
@@ -176,15 +176,15 @@ func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) {
176176
statusCode = resp.Status[:i]
177177
}
178178
if len(statusCode) != 3 {
179-
return nil, &badStringError{"malformed HTTP status code", statusCode}
179+
return nil, badStringError("malformed HTTP status code", statusCode)
180180
}
181181
resp.StatusCode, err = strconv.Atoi(statusCode)
182182
if err != nil || resp.StatusCode < 0 {
183-
return nil, &badStringError{"malformed HTTP status code", statusCode}
183+
return nil, badStringError("malformed HTTP status code", statusCode)
184184
}
185185
var ok bool
186186
if resp.ProtoMajor, resp.ProtoMinor, ok = ParseHTTPVersion(resp.Proto); !ok {
187-
return nil, &badStringError{"malformed HTTP version", resp.Proto}
187+
return nil, badStringError("malformed HTTP version", resp.Proto)
188188
}
189189

190190
// Parse the response headers.

src/net/http/server.go

+1
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ func (srv *Server) newConn(rwc net.Conn) *conn {
629629
}
630630

631631
type readResult struct {
632+
_ incomparable
632633
n int
633634
err error
634635
b byte // byte read, if n == 1

src/net/http/transfer.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ func (t *transferWriter) writeHeader(w io.Writer, trace *httptrace.ClientTrace)
310310
k = CanonicalHeaderKey(k)
311311
switch k {
312312
case "Transfer-Encoding", "Trailer", "Content-Length":
313-
return &badStringError{"invalid Trailer key", k}
313+
return badStringError("invalid Trailer key", k)
314314
}
315315
keys = append(keys, k)
316316
}
@@ -637,7 +637,7 @@ func (t *transferReader) fixTransferEncoding() error {
637637
te[len(te)-1] = encoding
638638
}
639639
if len(te) > 1 {
640-
return &badStringError{"too many transfer encodings", strings.Join(te, ",")}
640+
return badStringError("too many transfer encodings", strings.Join(te, ","))
641641
}
642642
if len(te) > 0 {
643643
// RFC 7230 3.3.2 says "A sender MUST NOT send a
@@ -791,7 +791,7 @@ func fixTrailer(header Header, te []string) (Header, error) {
791791
switch key {
792792
case "Transfer-Encoding", "Trailer", "Content-Length":
793793
if err == nil {
794-
err = &badStringError{"bad trailer key", key}
794+
err = badStringError("bad trailer key", key)
795795
return
796796
}
797797
}
@@ -1055,7 +1055,7 @@ func parseContentLength(cl string) (int64, error) {
10551055
}
10561056
n, err := strconv.ParseInt(cl, 10, 64)
10571057
if err != nil || n < 0 {
1058-
return 0, &badStringError{"bad Content-Length", cl}
1058+
return 0, badStringError("bad Content-Length", cl)
10591059
}
10601060
return n, nil
10611061

src/net/http/transfer_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ func TestFixTransferEncoding(t *testing.T) {
290290
},
291291
{
292292
hdr: Header{"Transfer-Encoding": {"chunked, chunked", "identity", "chunked"}},
293-
wantErr: &badStringError{"too many transfer encodings", "chunked,chunked"},
293+
wantErr: badStringError("too many transfer encodings", "chunked,chunked"),
294294
},
295295
{
296296
hdr: Header{"Transfer-Encoding": {"chunked"}},

src/net/http/transport.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) {
518518
}
519519
if !isHTTP {
520520
req.closeBody()
521-
return nil, &badStringError{"unsupported protocol scheme", scheme}
521+
return nil, badStringError("unsupported protocol scheme", scheme)
522522
}
523523
if req.Method != "" && !validMethod(req.Method) {
524524
req.closeBody()
@@ -1696,6 +1696,7 @@ var _ io.ReaderFrom = (*persistConnWriter)(nil)
16961696
// https://proxy.com|http https to proxy, http to anywhere after that
16971697
//
16981698
type connectMethod struct {
1699+
_ incomparable
16991700
proxyURL *url.URL // nil for no proxy, else full proxy URL
17001701
targetScheme string // "http" or "https"
17011702
// 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
22502251
// the concrete type for a Response.Body on the 101 Switching
22512252
// Protocols response, as used by WebSockets, h2c, etc.
22522253
type readWriteCloserBody struct {
2254+
_ incomparable
22532255
br *bufio.Reader // used until empty
22542256
io.ReadWriteCloser
22552257
}
@@ -2350,11 +2352,13 @@ func (pc *persistConn) wroteRequest() bool {
23502352
// responseAndError is how the goroutine reading from an HTTP/1 server
23512353
// communicates with the goroutine doing the RoundTrip.
23522354
type responseAndError struct {
2355+
_ incomparable
23532356
res *Response // else use this response (see res method)
23542357
err error
23552358
}
23562359

23572360
type requestAndChan struct {
2361+
_ incomparable
23582362
req *Request
23592363
ch chan responseAndError // unbuffered; always send in select on callerGone
23602364

@@ -2687,6 +2691,7 @@ func (es *bodyEOFSignal) condfn(err error) error {
26872691
// gzipReader wraps a response body so it can lazily
26882692
// call gzip.NewReader on the first call to Read
26892693
type gzipReader struct {
2694+
_ incomparable
26902695
body *bodyEOFSignal // underlying HTTP/1 response body framing
26912696
zr *gzip.Reader // lazily-initialized gzip reader
26922697
zerr error // any error from gzip.NewReader; sticky

0 commit comments

Comments
 (0)