dubbo.apache.org/dubbo-go/v3@v3.1.1/xds/client/resource/name.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* 19 * 20 * Copyright 2021 gRPC authors. 21 * 22 */ 23 24 package resource 25 26 import ( 27 "net/url" 28 "sort" 29 "strings" 30 ) 31 32 import ( 33 "dubbo.apache.org/dubbo-go/v3/xds/utils/envconfig" 34 ) 35 36 // Name contains the parsed component of an xDS resource name. 37 // 38 // An xDS resource name is in the format of 39 // xdstp://[{authority}]/{resource type}/{id/*}?{context parameters}{#processing directive,*} 40 // 41 // See 42 // https://github.com/cncf/xds/blob/main/proposals/TP1-xds-transport-next.md#uri-based-xds-resource-names 43 // for details, and examples. 44 type Name struct { 45 Scheme string 46 Authority string 47 Type string 48 ID string 49 50 ContextParams map[string]string 51 52 processingDirective string 53 } 54 55 // ParseName splits the name and returns a struct representation of the Name. 56 // 57 // If the name isn't a valid new-style xDS name, field ID is set to the input. 58 // Note that this is not an error, because we still support the old-style 59 // resource names (those not starting with "xdstp:"). 60 // 61 // The caller can tell if the parsing is successful by checking the returned 62 // Scheme. 63 func ParseName(name string) *Name { 64 if !envconfig.XDSFederation { 65 // Return "" scheme to use the default authority for the server. 66 return &Name{ID: name} 67 } 68 if !strings.Contains(name, "://") { 69 // Only the long form URL, with ://, is valid. 70 return &Name{ID: name} 71 } 72 parsed, err := url.Parse(name) 73 if err != nil { 74 return &Name{ID: name} 75 } 76 77 ret := &Name{ 78 Scheme: parsed.Scheme, 79 Authority: parsed.Host, 80 } 81 split := strings.SplitN(parsed.Path, "/", 3) 82 if len(split) < 3 { 83 // Path is in the format of "/type/id". There must be at least 3 84 // segments after splitting. 85 return &Name{ID: name} 86 } 87 ret.Type = split[1] 88 ret.ID = split[2] 89 if len(parsed.Query()) != 0 { 90 ret.ContextParams = make(map[string]string) 91 for k, vs := range parsed.Query() { 92 if len(vs) > 0 { 93 // We only keep one value of each key. Behavior for multiple values 94 // is undefined. 95 ret.ContextParams[k] = vs[0] 96 } 97 } 98 } 99 // TODO: processing directive (the part comes after "#" in the URL, stored 100 // in parsed.RawFragment) is kept but not processed. Add support for that 101 // when it's needed. 102 ret.processingDirective = parsed.RawFragment 103 return ret 104 } 105 106 // String returns a canonicalized string of name. The context parameters are 107 // sorted by the keys. 108 func (n *Name) String() string { 109 if n.Scheme == "" { 110 return n.ID 111 } 112 113 // Sort and build query. 114 keys := make([]string, 0, len(n.ContextParams)) 115 for k := range n.ContextParams { 116 keys = append(keys, k) 117 } 118 sort.Strings(keys) 119 var pairs []string 120 for _, k := range keys { 121 pairs = append(pairs, strings.Join([]string{k, n.ContextParams[k]}, "=")) 122 } 123 rawQuery := strings.Join(pairs, "&") 124 125 path := n.Type 126 if n.ID != "" { 127 path = path + "/" + n.ID 128 } 129 130 tempURL := &url.URL{ 131 Scheme: n.Scheme, 132 Host: n.Authority, 133 Path: path, 134 RawQuery: rawQuery, 135 RawFragment: n.processingDirective, 136 } 137 return tempURL.String() 138 }