github.com/viant/toolbox@v0.34.5/uri.go (about) 1 package toolbox 2 3 import ( 4 "fmt" 5 "net/url" 6 "os" 7 "path/filepath" 8 "strings" 9 ) 10 11 //ExtractURIParameters parses URIs to extract {<param>} defined in templateURI from requestURI, it returns extracted parameters and flag if requestURI matched templateURI 12 func ExtractURIParameters(templateURI, requestURI string) (map[string]string, bool) { 13 var expectingValue, expectingName bool 14 var name, value string 15 var uriParameters = make(map[string]string) 16 maxLength := len(templateURI) + len(requestURI) 17 var requestURIIndex, templateURIIndex int 18 19 questionMarkPosition := strings.Index(requestURI, "?") 20 if questionMarkPosition != -1 { 21 requestURI = string(requestURI[:questionMarkPosition]) 22 } 23 24 for k := 0; k < maxLength; k++ { 25 var requestChar, routingChar string 26 27 if requestURIIndex < len(requestURI) { 28 requestChar = requestURI[requestURIIndex : requestURIIndex+1] 29 } 30 31 if templateURIIndex < len(templateURI) { 32 routingChar = templateURI[templateURIIndex : templateURIIndex+1] 33 } 34 if (!expectingValue && !expectingName) && requestChar == routingChar && routingChar != "" { 35 requestURIIndex++ 36 templateURIIndex++ 37 continue 38 } 39 40 if routingChar == "}" { 41 expectingName = false 42 templateURIIndex++ 43 } 44 45 if expectingValue && requestChar == "/" { 46 expectingValue = false 47 } 48 49 if expectingName && templateURIIndex < len(templateURI) { 50 name += routingChar 51 templateURIIndex++ 52 } 53 54 if routingChar == "{" { 55 expectingValue = true 56 expectingName = true 57 templateURIIndex++ 58 59 } 60 61 if expectingValue && requestURIIndex < len(requestURI) { 62 value += requestChar 63 requestURIIndex++ 64 } 65 66 if !expectingValue && !expectingName && len(name) > 0 { 67 uriParameters[name] = value 68 name = "" 69 value = "" 70 } 71 72 } 73 74 if len(name) > 0 && len(value) > 0 { 75 uriParameters[name] = value 76 } 77 matched := requestURIIndex == len(requestURI) && templateURIIndex == len(templateURI) 78 return uriParameters, matched 79 } 80 81 82 83 //URLStripPath removes path from URL 84 func URLStripPath(URL string) string { 85 protoIndex := strings.Index(URL, "://") 86 if protoIndex != -1 { 87 pathIndex := strings.Index(string(URL[protoIndex+3:]), "/") 88 if pathIndex != -1 { 89 return string(URL[:protoIndex+3+pathIndex]) 90 } 91 } 92 return URL 93 } 94 95 //URLPathJoin joins URL paths 96 func URLPathJoin(baseURL, path string) string { 97 if path == "" { 98 return baseURL 99 } 100 if strings.HasPrefix(path, "/") { 101 return URLStripPath(baseURL) + path 102 } 103 104 if !strings.HasSuffix(baseURL, "/") { 105 baseURL += "/" 106 } 107 return baseURL + path 108 } 109 110 //URLBase returns base URL 111 func URLBase(URL string) string { 112 parsedURL, err := url.Parse(URL) 113 if err != nil || parsedURL.Path == "" { 114 return URL 115 } 116 pathPosition := strings.Index(URL, parsedURL.Path) 117 if pathPosition == -1 { 118 return URL 119 } 120 return string(URL[:pathPosition]) 121 } 122 123 //URLSplit returns URL with parent path and resource name 124 func URLSplit(URL string) (string, string) { 125 parsedURL, err := url.Parse(URL) 126 if err != nil || parsedURL.Path == "" { 127 return URL, "" 128 } 129 splitPosition := strings.LastIndex(parsedURL.Path, "/") 130 if splitPosition == -1 { 131 return URL, "" 132 } 133 return fmt.Sprintf("%v%v", URLBase(URL), string(parsedURL.Path[:splitPosition])), string(parsedURL.Path[splitPosition+1:]) 134 } 135 136 //Filename reformat file name 137 func Filename(filename string) string { 138 if strings.Contains(filename, ":/") { 139 if parsed, err := url.Parse(filename); err == nil { 140 filename = parsed.Path 141 } 142 } 143 var root = make([]string, 0) 144 if strings.HasPrefix(filename, "/") { 145 root = append(root, "/") 146 } 147 148 elements := append(root, strings.Split(filename, "/")...) 149 filename = filepath.Join(elements...) 150 return filename 151 } 152 153 //OpenFile open file converting path to elements and rebuling path safety with path.Join 154 func OpenFile(filename string) (*os.File, error) { 155 var file = Filename(filename) 156 var result, err = os.Open(file) 157 return result, err 158 }