Преглед изворни кода

all: use strs.CutPrefix and strs.CutSuffix more

Updates places where we use HasPrefix + TrimPrefix to use the combined
function.

Updates #5309

Signed-off-by: Mihai Parparita <[email protected]>
Mihai Parparita пре 3 година
родитељ
комит
33520920c3

+ 1 - 1
cmd/derper/depaware.txt

@@ -78,7 +78,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
         tailscale.com/util/lineread                                  from tailscale.com/hostinfo+
         tailscale.com/util/mak                                       from tailscale.com/syncs
         tailscale.com/util/singleflight                              from tailscale.com/net/dnscache
-   L    tailscale.com/util/strs                                      from tailscale.com/hostinfo
+        tailscale.com/util/strs                                      from tailscale.com/hostinfo+
    W 💣 tailscale.com/util/winutil                                   from tailscale.com/hostinfo+
         tailscale.com/version                                        from tailscale.com/derp+
         tailscale.com/version/distro                                 from tailscale.com/hostinfo+

+ 2 - 2
cmd/derper/mesh.go

@@ -17,6 +17,7 @@ import (
 	"tailscale.com/derp/derphttp"
 	"tailscale.com/types/key"
 	"tailscale.com/types/logger"
+	"tailscale.com/util/strs"
 )
 
 func startMesh(s *derp.Server) error {
@@ -50,8 +51,7 @@ func startMeshWithHost(s *derp.Server, host string) error {
 		}
 		var d net.Dialer
 		var r net.Resolver
-		if port == "443" && strings.HasSuffix(host, ".tailscale.com") {
-			base := strings.TrimSuffix(host, ".tailscale.com")
+		if base, ok := strs.CutSuffix(host, ".tailscale.com"); ok && port == "443" {
 			subCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
 			defer cancel()
 			vpcHost := base + "-vpc.tailscale.com"

+ 3 - 3
cmd/tailscale/cli/debug.go

@@ -37,6 +37,7 @@ import (
 	"tailscale.com/tailcfg"
 	"tailscale.com/types/key"
 	"tailscale.com/types/logger"
+	"tailscale.com/util/strs"
 )
 
 var debugCmd = &ffcli.Command{
@@ -228,9 +229,8 @@ func runDebug(ctx context.Context, args []string) error {
 			e.Encode(wfs)
 			return nil
 		}
-		delete := strings.HasPrefix(debugArgs.file, "delete:")
-		if delete {
-			return localClient.DeleteWaitingFile(ctx, strings.TrimPrefix(debugArgs.file, "delete:"))
+		if name, ok := strs.CutPrefix(debugArgs.file, "delete:"); ok {
+			return localClient.DeleteWaitingFile(ctx, name)
 		}
 		rc, size, err := localClient.GetWaitingFile(ctx, debugArgs.file)
 		if err != nil {

+ 3 - 2
cmd/tailscale/cli/file.go

@@ -30,6 +30,7 @@ import (
 	"tailscale.com/net/tsaddr"
 	"tailscale.com/tailcfg"
 	"tailscale.com/util/quarantine"
+	"tailscale.com/util/strs"
 	"tailscale.com/version"
 )
 
@@ -77,10 +78,10 @@ func runCp(ctx context.Context, args []string) error {
 		return errors.New("usage: tailscale file cp <files...> <target>:")
 	}
 	files, target := args[:len(args)-1], args[len(args)-1]
-	if !strings.HasSuffix(target, ":") {
+	target, ok := strs.CutSuffix(target, ":")
+	if !ok {
 		return fmt.Errorf("final argument to 'tailscale file cp' must end in colon")
 	}
-	target = strings.TrimSuffix(target, ":")
 	hadBrackets := false
 	if strings.HasPrefix(target, "[") && strings.HasSuffix(target, "]") {
 		hadBrackets = true

+ 2 - 2
cmd/tailscale/cli/up.go

@@ -33,6 +33,7 @@ import (
 	"tailscale.com/tailcfg"
 	"tailscale.com/types/logger"
 	"tailscale.com/types/preftype"
+	"tailscale.com/util/strs"
 	"tailscale.com/version"
 	"tailscale.com/version/distro"
 )
@@ -166,8 +167,7 @@ type upArgsT struct {
 
 func (a upArgsT) getAuthKey() (string, error) {
 	v := a.authKeyOrFile
-	if strings.HasPrefix(v, "file:") {
-		file := strings.TrimPrefix(v, "file:")
+	if file, ok := strs.CutPrefix(v, "file:"); ok {
 		b, err := os.ReadFile(file)
 		if err != nil {
 			return "", err

+ 1 - 1
cmd/tailscale/depaware.txt

@@ -108,7 +108,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
         tailscale.com/util/multierr                                  from tailscale.com/control/controlhttp
         tailscale.com/util/quarantine                                from tailscale.com/cmd/tailscale/cli
         tailscale.com/util/singleflight                              from tailscale.com/net/dnscache
-   L    tailscale.com/util/strs                                      from tailscale.com/hostinfo
+        tailscale.com/util/strs                                      from tailscale.com/hostinfo+
    W 💣 tailscale.com/util/winutil                                   from tailscale.com/hostinfo+
         tailscale.com/version                                        from tailscale.com/cmd/tailscale/cli+
         tailscale.com/version/distro                                 from tailscale.com/cmd/tailscale/cli+

+ 4 - 3
derp/derphttp/derphttp_client.go

@@ -24,7 +24,6 @@ import (
 	"net/netip"
 	"net/url"
 	"runtime"
-	"strings"
 	"sync"
 	"time"
 
@@ -39,6 +38,7 @@ import (
 	"tailscale.com/tailcfg"
 	"tailscale.com/types/key"
 	"tailscale.com/types/logger"
+	"tailscale.com/util/strs"
 )
 
 // Client is a DERP-over-HTTP client.
@@ -1028,9 +1028,10 @@ var ErrClientClosed = errors.New("derphttp.Client closed")
 
 func parseMetaCert(certs []*x509.Certificate) (serverPub key.NodePublic, serverProtoVersion int) {
 	for _, cert := range certs {
-		if cn := cert.Subject.CommonName; strings.HasPrefix(cn, "derpkey") {
+		// Look for derpkey prefix added by initMetacert() on the server side.
+		if pubHex, ok := strs.CutPrefix(cert.Subject.CommonName, "derpkey"); ok {
 			var err error
-			serverPub, err = key.ParseNodePublicUntyped(mem.S(strings.TrimPrefix(cn, "derpkey")))
+			serverPub, err = key.ParseNodePublicUntyped(mem.S(pubHex))
 			if err == nil && cert.SerialNumber.BitLen() <= 8 { // supports up to version 255
 				return serverPub, int(cert.SerialNumber.Int64())
 			}

+ 3 - 3
disco/disco_test.go

@@ -8,11 +8,11 @@ import (
 	"fmt"
 	"net/netip"
 	"reflect"
-	"strings"
 	"testing"
 
 	"go4.org/mem"
 	"tailscale.com/types/key"
+	"tailscale.com/util/strs"
 )
 
 func TestMarshalAndParse(t *testing.T) {
@@ -72,10 +72,10 @@ func TestMarshalAndParse(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			foo := []byte("foo")
 			got := string(tt.m.AppendMarshal(foo))
-			if !strings.HasPrefix(got, "foo") {
+			got, ok := strs.CutPrefix(got, "foo")
+			if !ok {
 				t.Fatalf("didn't start with foo: got %q", got)
 			}
-			got = strings.TrimPrefix(got, "foo")
 
 			gotHex := fmt.Sprintf("% x", got)
 			if gotHex != tt.want {

+ 4 - 4
ipn/ipnlocal/peerapi.go

@@ -166,13 +166,13 @@ func (s *peerAPIServer) hasFilesWaiting() bool {
 			if strings.HasSuffix(name, partialSuffix) {
 				continue
 			}
-			if strings.HasSuffix(name, deletedSuffix) { // for Windows + tests
+			if name, ok := strs.CutSuffix(name, deletedSuffix); ok { // for Windows + tests
 				// After we're done looping over files, then try
 				// to delete this file. Don't do it proactively,
 				// as the OS may return "foo.jpg.deleted" before "foo.jpg"
 				// and we don't want to delete the ".deleted" file before
 				// enumerating to the "foo.jpg" file.
-				defer tryDeleteAgain(filepath.Join(s.rootDir, strings.TrimSuffix(name, deletedSuffix)))
+				defer tryDeleteAgain(filepath.Join(s.rootDir, name))
 				continue
 			}
 			if de.Type().IsRegular() {
@@ -225,11 +225,11 @@ func (s *peerAPIServer) WaitingFiles() (ret []apitype.WaitingFile, err error) {
 			if strings.HasSuffix(name, partialSuffix) {
 				continue
 			}
-			if strings.HasSuffix(name, deletedSuffix) { // for Windows + tests
+			if name, ok := strs.CutSuffix(name, deletedSuffix); ok { // for Windows + tests
 				if deleted == nil {
 					deleted = map[string]bool{}
 				}
-				deleted[strings.TrimSuffix(name, deletedSuffix)] = true
+				deleted[name] = true
 				continue
 			}
 			if de.Type().IsRegular() {

+ 12 - 3
ipn/localapi/localapi.go

@@ -670,7 +670,11 @@ func (h *Handler) serveFiles(w http.ResponseWriter, r *http.Request) {
 		http.Error(w, "file access denied", http.StatusForbidden)
 		return
 	}
-	suffix := strings.TrimPrefix(r.URL.EscapedPath(), "/localapi/v0/files/")
+	suffix, ok := strs.CutPrefix(r.URL.EscapedPath(), "/localapi/v0/files/")
+	if !ok {
+		http.Error(w, "misconfigured", http.StatusInternalServerError)
+		return
+	}
 	if suffix == "" {
 		if r.Method != "GET" {
 			http.Error(w, "want GET to list files", 400)
@@ -774,7 +778,11 @@ func (h *Handler) serveFilePut(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	upath := strings.TrimPrefix(r.URL.EscapedPath(), "/localapi/v0/file-put/")
+	upath, ok := strs.CutPrefix(r.URL.EscapedPath(), "/localapi/v0/file-put/")
+	if !ok {
+		http.Error(w, "misconfigured", http.StatusInternalServerError)
+		return
+	}
 	stableIDStr, filenameEscaped, ok := strings.Cut(upath, "/")
 	if !ok {
 		http.Error(w, "bogus URL", 400)
@@ -1159,7 +1167,8 @@ func (h *Handler) serveProfiles(w http.ResponseWriter, r *http.Request) {
 	}
 	suffix, ok := strs.CutPrefix(r.URL.EscapedPath(), "/localapi/v0/profiles/")
 	if !ok {
-		panic("misconfigured")
+		http.Error(w, "misconfigured", http.StatusInternalServerError)
+		return
 	}
 	if suffix == "" {
 		switch r.Method {

+ 3 - 4
net/dns/resolvconffile/resolvconffile.go

@@ -21,6 +21,7 @@ import (
 	"strings"
 
 	"tailscale.com/util/dnsname"
+	"tailscale.com/util/strs"
 )
 
 // Path is the canonical location of resolv.conf.
@@ -68,8 +69,7 @@ func Parse(r io.Reader) (*Config, error) {
 		line, _, _ = strings.Cut(line, "#") // remove any comments
 		line = strings.TrimSpace(line)
 
-		if strings.HasPrefix(line, "nameserver") {
-			s := strings.TrimPrefix(line, "nameserver")
+		if s, ok := strs.CutPrefix(line, "nameserver"); ok {
 			nameserver := strings.TrimSpace(s)
 			if len(nameserver) == len(s) {
 				return nil, fmt.Errorf("missing space after \"nameserver\" in %q", line)
@@ -82,8 +82,7 @@ func Parse(r io.Reader) (*Config, error) {
 			continue
 		}
 
-		if strings.HasPrefix(line, "search") {
-			s := strings.TrimPrefix(line, "search")
+		if s, ok := strs.CutPrefix(line, "search"); ok {
 			domain := strings.TrimSpace(s)
 			if len(domain) == len(s) {
 				// No leading space?!

+ 2 - 2
net/dns/resolver/tsdns.go

@@ -34,6 +34,7 @@ import (
 	"tailscale.com/util/clientmetric"
 	"tailscale.com/util/cloudenv"
 	"tailscale.com/util/dnsname"
+	"tailscale.com/util/strs"
 	"tailscale.com/wgengine/monitor"
 )
 
@@ -1215,8 +1216,7 @@ func (r *Resolver) respond(query []byte) ([]byte, error) {
 // unARPA maps from "4.4.8.8.in-addr.arpa." to "8.8.4.4", etc.
 func unARPA(a string) (ipStr string, ok bool) {
 	const suf4 = ".in-addr.arpa."
-	if strings.HasSuffix(a, suf4) {
-		s := strings.TrimSuffix(a, suf4)
+	if s, ok := strs.CutSuffix(a, suf4); ok {
 		// Parse and reverse octets.
 		ip, err := netip.ParseAddr(s)
 		if err != nil || !ip.Is4() {

+ 2 - 1
tsweb/tsweb.go

@@ -32,6 +32,7 @@ import (
 	"tailscale.com/metrics"
 	"tailscale.com/net/tsaddr"
 	"tailscale.com/types/logger"
+	"tailscale.com/util/strs"
 	"tailscale.com/version"
 )
 
@@ -740,7 +741,7 @@ func structTypeSortedFields(t reflect.Type) []sortedStructField {
 // removed.
 func removeTypePrefixes(s string) string {
 	for _, prefix := range prefixesToTrim {
-		if trimmed := strings.TrimPrefix(s, prefix); trimmed != s {
+		if trimmed, ok := strs.CutPrefix(s, prefix); ok {
 			return trimmed
 		}
 	}

+ 4 - 3
version/cmdname.go

@@ -15,6 +15,8 @@ import (
 	"path"
 	"path/filepath"
 	"strings"
+
+	"tailscale.com/util/strs"
 )
 
 // CmdName returns either the base name of the current binary
@@ -41,9 +43,8 @@ func cmdName(exe string) string {
 	// v is like:
 	// "path\ttailscale.com/cmd/tailscale\nmod\ttailscale.com\t(devel)\t\ndep\tgithub.com/apenwarr/fixconsole\tv0.0.0-20191012055117-5a9f6489cc29\th1:muXWUcay7DDy1/hEQWrYlBy+g0EuwT70sBHg65SeUc4=\ndep\tgithub....
 	for _, line := range strings.Split(info, "\n") {
-		if strings.HasPrefix(line, "path\t") {
-			goPkg := strings.TrimPrefix(line, "path\t") // like "tailscale.com/cmd/tailscale"
-			ret = path.Base(goPkg)                      // goPkg is always forward slashes; use path, not filepath
+		if goPkg, ok := strs.CutPrefix(line, "path\t"); ok { // like "tailscale.com/cmd/tailscale"
+			ret = path.Base(goPkg) // goPkg is always forward slashes; use path, not filepath
 			break
 		}
 	}