istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/config/host/name.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package host
    16  
    17  import (
    18  	"strings"
    19  )
    20  
    21  // Name describes a (possibly wildcarded) hostname
    22  type Name string
    23  
    24  // Matches returns true if this hostname overlaps with the other hostname. Names overlap if:
    25  // - they're fully resolved (i.e. not wildcarded) and match exactly (i.e. an exact string match)
    26  // - one or both are wildcarded (e.g. "*.foo.com"), in which case we use wildcard resolution rules
    27  // to determine if n is covered by o or o is covered by n.
    28  // e.g.:
    29  //
    30  //	Name("foo.com").Matches("foo.com")   = true
    31  //	Name("foo.com").Matches("bar.com")   = false
    32  //	Name("*.com").Matches("foo.com")     = true
    33  //	Name("bar.com").Matches("*.com")     = true
    34  //	Name("*.foo.com").Matches("foo.com") = false
    35  //	Name("*").Matches("foo.com")         = true
    36  //	Name("*").Matches("*.com")           = true
    37  func (n Name) Matches(o Name) bool {
    38  	hWildcard := n.IsWildCarded()
    39  	oWildcard := o.IsWildCarded()
    40  
    41  	if hWildcard {
    42  		if oWildcard {
    43  			// both n and o are wildcards
    44  			if len(n) < len(o) {
    45  				return strings.HasSuffix(string(o[1:]), string(n[1:]))
    46  			}
    47  			return strings.HasSuffix(string(n[1:]), string(o[1:]))
    48  		}
    49  		// only n is wildcard
    50  		return strings.HasSuffix(string(o), string(n[1:]))
    51  	}
    52  
    53  	if oWildcard {
    54  		// only o is wildcard
    55  		return strings.HasSuffix(string(n), string(o[1:]))
    56  	}
    57  
    58  	// both are non-wildcards, so do normal string comparison
    59  	return n == o
    60  }
    61  
    62  // SubsetOf returns true if this hostname is a valid subset of the other hostname. The semantics are
    63  // the same as "Matches", but only in one direction (i.e., n is covered by o).
    64  func (n Name) SubsetOf(o Name) bool {
    65  	hWildcard := n.IsWildCarded()
    66  	oWildcard := o.IsWildCarded()
    67  
    68  	if hWildcard {
    69  		if oWildcard {
    70  			// both n and o are wildcards
    71  			if len(n) < len(o) {
    72  				return false
    73  			}
    74  			return strings.HasSuffix(string(n[1:]), string(o[1:]))
    75  		}
    76  		// only n is wildcard
    77  		return false
    78  	}
    79  
    80  	if oWildcard {
    81  		// only o is wildcard
    82  		return strings.HasSuffix(string(n), string(o[1:]))
    83  	}
    84  
    85  	// both are non-wildcards, so do normal string comparison
    86  	return n == o
    87  }
    88  
    89  func (n Name) IsWildCarded() bool {
    90  	return len(n) > 0 && n[0] == '*'
    91  }
    92  
    93  func (n Name) String() string {
    94  	return string(n)
    95  }