aboutsummaryrefslogtreecommitdiff
path: root/src/net/http
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2021-09-22 10:46:32 -0400
committerRuss Cox <rsc@golang.org>2021-10-06 15:53:04 +0000
commit4d8db00641cc9ff4f44de7df9b8c4f4a4f9416ee (patch)
tree1e850efb295d4c5f0589e46bd8d9f1930d4af0b5 /src/net/http
parent8e36ab055162efa6f67f3b9ee62f625ac8874901 (diff)
downloadgo-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.go4
-rw-r--r--src/net/http/cgi/host.go5
-rw-r--r--src/net/http/cgi/host_test.go10
-rw-r--r--src/net/http/client_test.go7
-rw-r--r--src/net/http/cookie.go27
-rw-r--r--src/net/http/fs.go6
-rw-r--r--src/net/http/internal/chunked.go9
-rw-r--r--src/net/http/main_test.go7
-rw-r--r--src/net/http/request.go25
-rw-r--r--src/net/http/response.go15
-rw-r--r--src/net/http/server.go2
-rw-r--r--src/net/http/transport.go6
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)
}
}