go-hep.org/x/hep@v0.40.0/xrootd/xrdio/parse.go (about) 1 // Copyright ©2018 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package xrdio 6 7 import ( 8 "fmt" 9 "net" 10 "strings" 11 ) 12 13 // URL stores an absolute reference to a XRootD path. 14 type URL struct { 15 Addr string // address (host [:port]) of the server 16 User string // user name to use to log in 17 Path string // path to the remote file or directory 18 } 19 20 // Parse parses name into an xrootd URL structure. 21 func Parse(name string) (URL, error) { 22 // FIXME(sbinet): just use url.Parse instead ? 23 24 var ( 25 user string 26 addr string 27 path string 28 err error 29 ) 30 31 idx := strings.Index(name, "://") 32 switch idx { 33 case -1: 34 path = name 35 default: 36 uri := name[idx+len("://"):] 37 tok := strings.SplitN(uri, "/", 2) 38 user, addr, err = parseUA(tok[0]) 39 if err != nil { 40 return URL{}, fmt.Errorf("could not parse URI %q: %w", name, err) 41 } 42 path = "/" + tok[1] 43 } 44 45 if strings.HasPrefix(path, "//") { 46 path = path[1:] 47 } 48 49 return URL{Addr: addr, User: user, Path: path}, nil 50 } 51 52 func parseUA(s string) (user, addr string, err error) { 53 switch { 54 case strings.Contains(s, "@"): 55 toks := strings.SplitN(s, "@", 2) 56 user = parseUser(toks[0]) 57 addr = toks[1] 58 default: 59 addr = s 60 } 61 62 switch { 63 case strings.HasPrefix(addr, "["): // IPv6 literal 64 idx := strings.LastIndex(addr, "]") 65 col := strings.Index(addr[idx+1:], ":") 66 if col >= 0 { 67 _, _, err = net.SplitHostPort(addr) 68 } 69 case strings.Contains(addr, ":"): 70 _, _, err = net.SplitHostPort(addr) 71 } 72 73 if err != nil { 74 return "", "", fmt.Errorf("could not extract host+port from URI: %w", err) 75 } 76 77 return user, addr, nil 78 } 79 80 func parseUser(s string) string { 81 usr, _, ok := strings.Cut(s, ":") 82 if !ok { 83 return s 84 } 85 return usr 86 }