diff options
| author | Russ Cox <rsc@golang.org> | 2021-09-22 10:46:32 -0400 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2021-10-06 15:53:04 +0000 |
| commit | 4d8db00641cc9ff4f44de7df9b8c4f4a4f9416ee (patch) | |
| tree | 1e850efb295d4c5f0589e46bd8d9f1930d4af0b5 /src/net/http | |
| parent | 8e36ab055162efa6f67f3b9ee62f625ac8874901 (diff) | |
| download | go-4d8db00641cc9ff4f44de7df9b8c4f4a4f9416ee.tar.xz | |
all: use bytes.Cut, strings.Cut
Many uses of Index/IndexByte/IndexRune/Split/SplitN
can be written more clearly using the new Cut functions.
Do that. Also rewrite to other functions if that's clearer.
For #46336.
Change-Id: I68d024716ace41a57a8bf74455c62279bde0f448
Reviewed-on: https://go-review.googlesource.com/c/go/+/351711
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/net/http')
| -rw-r--r-- | src/net/http/cgi/child.go | 4 | ||||
| -rw-r--r-- | src/net/http/cgi/host.go | 5 | ||||
| -rw-r--r-- | src/net/http/cgi/host_test.go | 10 | ||||
| -rw-r--r-- | src/net/http/client_test.go | 7 | ||||
| -rw-r--r-- | src/net/http/cookie.go | 27 | ||||
| -rw-r--r-- | src/net/http/fs.go | 6 | ||||
| -rw-r--r-- | src/net/http/internal/chunked.go | 9 | ||||
| -rw-r--r-- | src/net/http/main_test.go | 7 | ||||
| -rw-r--r-- | src/net/http/request.go | 25 | ||||
| -rw-r--r-- | src/net/http/response.go | 15 | ||||
| -rw-r--r-- | src/net/http/server.go | 2 | ||||
| -rw-r--r-- | src/net/http/transport.go | 6 |
12 files changed, 51 insertions, 72 deletions
diff --git a/src/net/http/cgi/child.go b/src/net/http/cgi/child.go index 0114da377b..bdb35a64e5 100644 --- a/src/net/http/cgi/child.go +++ b/src/net/http/cgi/child.go @@ -39,8 +39,8 @@ func Request() (*http.Request, error) { func envMap(env []string) map[string]string { m := make(map[string]string) for _, kv := range env { - if idx := strings.Index(kv, "="); idx != -1 { - m[kv[:idx]] = kv[idx+1:] + if k, v, ok := strings.Cut(kv, "="); ok { + m[k] = v } } return m diff --git a/src/net/http/cgi/host.go b/src/net/http/cgi/host.go index eff67caf4e..e7124a2ab0 100644 --- a/src/net/http/cgi/host.go +++ b/src/net/http/cgi/host.go @@ -273,12 +273,11 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { break } headerLines++ - parts := strings.SplitN(string(line), ":", 2) - if len(parts) < 2 { + header, val, ok := strings.Cut(string(line), ":") + if !ok { h.printf("cgi: bogus header line: %s", string(line)) continue } - header, val := parts[0], parts[1] if !httpguts.ValidHeaderFieldName(header) { h.printf("cgi: invalid header name: %q", header) continue diff --git a/src/net/http/cgi/host_test.go b/src/net/http/cgi/host_test.go index fb869a6728..f8abc88c89 100644 --- a/src/net/http/cgi/host_test.go +++ b/src/net/http/cgi/host_test.go @@ -62,12 +62,12 @@ readlines: } linesRead++ trimmedLine := strings.TrimRight(line, "\r\n") - split := strings.SplitN(trimmedLine, "=", 2) - if len(split) != 2 { - t.Fatalf("Unexpected %d parts from invalid line number %v: %q; existing map=%v", - len(split), linesRead, line, m) + k, v, ok := strings.Cut(trimmedLine, "=") + if !ok { + t.Fatalf("Unexpected response from invalid line number %v: %q; existing map=%v", + linesRead, line, m) } - m[split[0]] = split[1] + m[k] = v } for key, expected := range expectedMap { diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go index 05ed2268b5..e741c3746f 100644 --- a/src/net/http/client_test.go +++ b/src/net/http/client_test.go @@ -431,11 +431,10 @@ func testRedirectsByMethod(t *testing.T, method string, table []redirectTest, wa if v := urlQuery.Get("code"); v != "" { location := ts.URL if final := urlQuery.Get("next"); final != "" { - splits := strings.Split(final, ",") - first, rest := splits[0], splits[1:] + first, rest, _ := strings.Cut(final, ",") location = fmt.Sprintf("%s?code=%s", location, first) - if len(rest) > 0 { - location = fmt.Sprintf("%s&next=%s", location, strings.Join(rest, ",")) + if rest != "" { + location = fmt.Sprintf("%s&next=%s", location, rest) } } code, _ := strconv.Atoi(v) diff --git a/src/net/http/cookie.go b/src/net/http/cookie.go index ca2c1c2506..02b40315de 100644 --- a/src/net/http/cookie.go +++ b/src/net/http/cookie.go @@ -67,15 +67,14 @@ func readSetCookies(h Header) []*Cookie { continue } parts[0] = textproto.TrimString(parts[0]) - j := strings.Index(parts[0], "=") - if j < 0 { + name, value, ok := strings.Cut(parts[0], "=") + if !ok { continue } - name, value := parts[0][:j], parts[0][j+1:] if !isCookieNameValid(name) { continue } - value, ok := parseCookieValue(value, true) + value, ok = parseCookieValue(value, true) if !ok { continue } @@ -90,10 +89,7 @@ func readSetCookies(h Header) []*Cookie { continue } - attr, val := parts[i], "" - if j := strings.Index(attr, "="); j >= 0 { - attr, val = attr[:j], attr[j+1:] - } + attr, val, _ := strings.Cut(parts[i], "=") lowerAttr, isASCII := ascii.ToLower(attr) if !isASCII { continue @@ -256,19 +252,12 @@ func readCookies(h Header, filter string) []*Cookie { var part string for len(line) > 0 { // continue since we have rest - if splitIndex := strings.Index(line, ";"); splitIndex > 0 { - part, line = line[:splitIndex], line[splitIndex+1:] - } else { - part, line = line, "" - } + part, line, _ = strings.Cut(line, ";") part = textproto.TrimString(part) - if len(part) == 0 { + if part == "" { continue } - name, val := part, "" - if j := strings.Index(part, "="); j >= 0 { - name, val = name[:j], name[j+1:] - } + name, val, _ := strings.Cut(part, "=") if !isCookieNameValid(name) { continue } @@ -379,7 +368,7 @@ func sanitizeCookieValue(v string) string { if len(v) == 0 { return v } - if strings.IndexByte(v, ' ') >= 0 || strings.IndexByte(v, ',') >= 0 { + if strings.ContainsAny(v, " ,") { return `"` + v + `"` } return v diff --git a/src/net/http/fs.go b/src/net/http/fs.go index 57e731e481..19b2894bf2 100644 --- a/src/net/http/fs.go +++ b/src/net/http/fs.go @@ -881,11 +881,11 @@ func parseRange(s string, size int64) ([]httpRange, error) { if ra == "" { continue } - i := strings.Index(ra, "-") - if i < 0 { + start, end, ok := strings.Cut(ra, "-") + if !ok { return nil, errors.New("invalid range") } - start, end := textproto.TrimString(ra[:i]), textproto.TrimString(ra[i+1:]) + start, end = textproto.TrimString(start), textproto.TrimString(end) var r httpRange if start == "" { // If no start is specified, end specifies the diff --git a/src/net/http/internal/chunked.go b/src/net/http/internal/chunked.go index f06e5725f3..923e6a6d2c 100644 --- a/src/net/http/internal/chunked.go +++ b/src/net/http/internal/chunked.go @@ -152,6 +152,8 @@ func isASCIISpace(b byte) bool { return b == ' ' || b == '\t' || b == '\n' || b == '\r' } +var semi = []byte(";") + // removeChunkExtension removes any chunk-extension from p. // For example, // "0" => "0" @@ -159,14 +161,11 @@ func isASCIISpace(b byte) bool { // "0;token=val" => "0" // `0;token="quoted string"` => "0" func removeChunkExtension(p []byte) ([]byte, error) { - semi := bytes.IndexByte(p, ';') - if semi == -1 { - return p, nil - } + p, _, _ = bytes.Cut(p, semi) // TODO: care about exact syntax of chunk extensions? We're // ignoring and stripping them anyway. For now just never // return an error. - return p[:semi], nil + return p, nil } // NewChunkedWriter returns a new chunkedWriter that translates writes into HTTP diff --git a/src/net/http/main_test.go b/src/net/http/main_test.go index 6564627998..632a308a5c 100644 --- a/src/net/http/main_test.go +++ b/src/net/http/main_test.go @@ -31,11 +31,8 @@ func interestingGoroutines() (gs []string) { buf := make([]byte, 2<<20) buf = buf[:runtime.Stack(buf, true)] for _, g := range strings.Split(string(buf), "\n\n") { - sl := strings.SplitN(g, "\n", 2) - if len(sl) != 2 { - continue - } - stack := strings.TrimSpace(sl[1]) + _, stack, _ := strings.Cut(g, "\n") + stack = strings.TrimSpace(stack) if stack == "" || strings.Contains(stack, "testing.(*M).before.func1") || strings.Contains(stack, "os/signal.signal_recv") || diff --git a/src/net/http/request.go b/src/net/http/request.go index 0eb7042d7b..76c2317d28 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -940,7 +940,7 @@ func NewRequestWithContext(ctx context.Context, method, url string, body io.Read func (r *Request) BasicAuth() (username, password string, ok bool) { auth := r.Header.Get("Authorization") if auth == "" { - return + return "", "", false } return parseBasicAuth(auth) } @@ -951,18 +951,18 @@ func parseBasicAuth(auth string) (username, password string, ok bool) { const prefix = "Basic " // Case insensitive prefix match. See Issue 22736. if len(auth) < len(prefix) || !ascii.EqualFold(auth[:len(prefix)], prefix) { - return + return "", "", false } c, err := base64.StdEncoding.DecodeString(auth[len(prefix):]) if err != nil { - return + return "", "", false } cs := string(c) - s := strings.IndexByte(cs, ':') - if s < 0 { - return + username, password, ok = strings.Cut(cs, ":") + if !ok { + return "", "", false } - return cs[:s], cs[s+1:], true + return username, password, true } // SetBasicAuth sets the request's Authorization header to use HTTP @@ -980,13 +980,12 @@ func (r *Request) SetBasicAuth(username, password string) { // parseRequestLine parses "GET /foo HTTP/1.1" into its three parts. func parseRequestLine(line string) (method, requestURI, proto string, ok bool) { - s1 := strings.Index(line, " ") - s2 := strings.Index(line[s1+1:], " ") - if s1 < 0 || s2 < 0 { - return + method, rest, ok1 := strings.Cut(line, " ") + requestURI, proto, ok2 := strings.Cut(rest, " ") + if !ok1 || !ok2 { + return "", "", "", false } - s2 += s1 + 1 - return line[:s1], line[s1+1 : s2], line[s2+1:], true + return method, requestURI, proto, true } var textprotoReaderPool sync.Pool diff --git a/src/net/http/response.go b/src/net/http/response.go index b8985da3c8..297394eabe 100644 --- a/src/net/http/response.go +++ b/src/net/http/response.go @@ -165,16 +165,14 @@ func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) { } return nil, err } - if i := strings.IndexByte(line, ' '); i == -1 { + proto, status, ok := strings.Cut(line, " ") + if !ok { return nil, badStringError("malformed HTTP response", line) - } else { - resp.Proto = line[:i] - resp.Status = strings.TrimLeft(line[i+1:], " ") - } - statusCode := resp.Status - if i := strings.IndexByte(resp.Status, ' '); i != -1 { - statusCode = resp.Status[:i] } + resp.Proto = proto + resp.Status = strings.TrimLeft(status, " ") + + statusCode, _, _ := strings.Cut(resp.Status, " ") if len(statusCode) != 3 { return nil, badStringError("malformed HTTP status code", statusCode) } @@ -182,7 +180,6 @@ func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) { if err != nil || resp.StatusCode < 0 { return nil, badStringError("malformed HTTP status code", statusCode) } - var ok bool if resp.ProtoMajor, resp.ProtoMinor, ok = ParseHTTPVersion(resp.Proto); !ok { return nil, badStringError("malformed HTTP version", resp.Proto) } diff --git a/src/net/http/server.go b/src/net/http/server.go index 4d0ce5619f..55fd4ae22f 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -2282,7 +2282,7 @@ func cleanPath(p string) string { // stripHostPort returns h without any trailing ":<port>". func stripHostPort(h string) string { // If no port on host, return unchanged - if strings.IndexByte(h, ':') == -1 { + if !strings.Contains(h, ":") { return h } host, _, err := net.SplitHostPort(h) diff --git a/src/net/http/transport.go b/src/net/http/transport.go index 309194e8e5..17f0047b59 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -1715,12 +1715,12 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers return nil, err } if resp.StatusCode != 200 { - f := strings.SplitN(resp.Status, " ", 2) + _, text, ok := strings.Cut(resp.Status, " ") conn.Close() - if len(f) < 2 { + if !ok { return nil, errors.New("unknown status code") } - return nil, errors.New(f[1]) + return nil, errors.New(text) } } |
