diff --git a/caddyconfig/load.go b/caddyconfig/load.go index bd47bea4..9f5cda90 100644 --- a/caddyconfig/load.go +++ b/caddyconfig/load.go @@ -189,12 +189,11 @@ func adaptByContentType(contentType string, body []byte) ([]byte, []Warning, err } // adapter name should be suffix of MIME type - slashIdx := strings.Index(ct, "/") - if slashIdx < 0 { + _, adapterName, slashFound := strings.Cut(ct, "/") + if !slashFound { return nil, nil, fmt.Errorf("malformed Content-Type") } - adapterName := ct[slashIdx+1:] cfgAdapter := GetAdapter(adapterName) if cfgAdapter == nil { return nil, nil, fmt.Errorf("unrecognized config adapter '%s'", adapterName) diff --git a/cmd/main.go b/cmd/main.go index e932b6b8..c475eaad 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -387,11 +387,11 @@ func parseEnvFile(envInput io.Reader) (map[string]string, error) { } // split line into key and value - fields := strings.SplitN(line, "=", 2) - if len(fields) != 2 { + before, after, isCut := strings.Cut(line, "=") + if !isCut { return nil, fmt.Errorf("can't parse line %d; line should be in KEY=VALUE format", lineNumber) } - key, val := fields[0], fields[1] + key, val := before, after // sometimes keys are prefixed by "export " so file can be sourced in bash; ignore it here key = strings.TrimPrefix(key, "export ") diff --git a/listeners.go b/listeners.go index d9cfbf28..3a8d49dd 100644 --- a/listeners.go +++ b/listeners.go @@ -468,15 +468,15 @@ func ParseNetworkAddress(addr string) (NetworkAddress, error) { } var start, end uint64 if port != "" { - ports := strings.SplitN(port, "-", 2) - if len(ports) == 1 { - ports = append(ports, ports[0]) + before, after, found := strings.Cut(port, "-") + if !found { + after = before } - start, err = strconv.ParseUint(ports[0], 10, 16) + start, err = strconv.ParseUint(before, 10, 16) if err != nil { return NetworkAddress{}, fmt.Errorf("invalid start port: %v", err) } - end, err = strconv.ParseUint(ports[1], 10, 16) + end, err = strconv.ParseUint(after, 10, 16) if err != nil { return NetworkAddress{}, fmt.Errorf("invalid end port: %v", err) } @@ -498,9 +498,10 @@ func ParseNetworkAddress(addr string) (NetworkAddress, error) { // SplitNetworkAddress splits a into its network, host, and port components. // Note that port may be a port range (:X-Y), or omitted for unix sockets. func SplitNetworkAddress(a string) (network, host, port string, err error) { - if idx := strings.Index(a, "/"); idx >= 0 { - network = strings.ToLower(strings.TrimSpace(a[:idx])) - a = a[idx+1:] + beforeSlash, afterSlash, slashFound := strings.Cut(a, "/") + if slashFound { + network = strings.ToLower(strings.TrimSpace(beforeSlash)) + a = afterSlash } if isUnixNetwork(network) { host = a diff --git a/modules.go b/modules.go index a57bc65e..e83bc747 100644 --- a/modules.go +++ b/modules.go @@ -324,11 +324,11 @@ func ParseStructTag(tag string) (map[string]string, error) { if pair == "" { continue } - parts := strings.SplitN(pair, "=", 2) - if len(parts) != 2 { + before, after, isCut := strings.Cut(pair, "=") + if !isCut { return nil, fmt.Errorf("missing key in '%s' (pair %d)", pair, i) } - results[parts[0]] = parts[1] + results[before] = after } return results, nil } diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go index 2eedaca2..bb957d6a 100644 --- a/modules/caddyhttp/matchers.go +++ b/modules/caddyhttp/matchers.go @@ -610,11 +610,11 @@ func (m *MatchQuery) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { if query == "" { continue } - parts := strings.SplitN(query, "=", 2) - if len(parts) != 2 { + before, after, found := strings.Cut(query, "=") + if !found { return d.Errf("malformed query matcher token: %s; must be in param=val format", d.Val()) } - url.Values(*m).Add(parts[0], parts[1]) + url.Values(*m).Add(before, after) } if d.NextBlock(0) { return d.Err("malformed query matcher: blocks are not supported") diff --git a/modules/caddyhttp/push/link.go b/modules/caddyhttp/push/link.go index 16b0e7d2..f7c1dd89 100644 --- a/modules/caddyhttp/push/link.go +++ b/modules/caddyhttp/push/link.go @@ -52,17 +52,16 @@ func parseLinkHeader(header string) []linkResource { l.uri = strings.TrimSpace(link[li+1 : ri]) for _, param := range strings.Split(strings.TrimSpace(link[ri+1:]), semicolon) { - parts := strings.SplitN(strings.TrimSpace(param), equal, 2) - key := strings.TrimSpace(parts[0]) + before, after, isCut := strings.Cut(strings.TrimSpace(param), equal) + key := strings.TrimSpace(before) if key == "" { continue } - if len(parts) == 1 { + if isCut { + l.params[key] = strings.TrimSpace(after) + } else { l.params[key] = key } - if len(parts) == 2 { - l.params[key] = strings.TrimSpace(parts[1]) - } } resources = append(resources, l) diff --git a/modules/caddyhttp/reverseproxy/addresses.go b/modules/caddyhttp/reverseproxy/addresses.go index f15ed76d..c161ed87 100644 --- a/modules/caddyhttp/reverseproxy/addresses.go +++ b/modules/caddyhttp/reverseproxy/addresses.go @@ -80,9 +80,9 @@ func parseUpstreamDialAddress(upstreamAddr string) (string, string, error) { scheme, host, port = toURL.Scheme, toURL.Hostname(), toURL.Port() } else { // extract network manually, since caddy.ParseNetworkAddress() will always add one - if idx := strings.Index(upstreamAddr, "/"); idx >= 0 { - network = strings.ToLower(strings.TrimSpace(upstreamAddr[:idx])) - upstreamAddr = upstreamAddr[idx+1:] + if beforeSlash, afterSlash, slashFound := strings.Cut(upstreamAddr, "/"); slashFound { + network = strings.ToLower(strings.TrimSpace(beforeSlash)) + upstreamAddr = afterSlash } var err error host, port, err = net.SplitHostPort(upstreamAddr) diff --git a/modules/caddyhttp/reverseproxy/fastcgi/client.go b/modules/caddyhttp/reverseproxy/fastcgi/client.go index 07720539..0fdcbfee 100644 --- a/modules/caddyhttp/reverseproxy/fastcgi/client.go +++ b/modules/caddyhttp/reverseproxy/fastcgi/client.go @@ -424,13 +424,13 @@ func (c *FCGIClient) Request(p map[string]string, req io.Reader) (resp *http.Res resp.Header = http.Header(mimeHeader) if resp.Header.Get("Status") != "" { - statusParts := strings.SplitN(resp.Header.Get("Status"), " ", 2) - resp.StatusCode, err = strconv.Atoi(statusParts[0]) + statusNumber, statusInfo, statusIsCut := strings.Cut(resp.Header.Get("Status"), " ") + resp.StatusCode, err = strconv.Atoi(statusNumber) if err != nil { return } - if len(statusParts) > 1 { - resp.Status = statusParts[1] + if statusIsCut { + resp.Status = statusInfo } } else {