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  }