go-hep.org/x/hep@v0.38.1/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  	var (
    23  		user string
    24  		addr string
    25  		path string
    26  		err  error
    27  	)
    28  
    29  	idx := strings.Index(name, "://")
    30  	switch idx {
    31  	case -1:
    32  		path = name
    33  	default:
    34  		uri := name[idx+len("://"):]
    35  		tok := strings.SplitN(uri, "/", 2)
    36  		user, addr, err = parseUA(tok[0])
    37  		if err != nil {
    38  			return URL{}, fmt.Errorf("could not parse URI %q: %w", name, err)
    39  		}
    40  		path = "/" + tok[1]
    41  	}
    42  
    43  	if strings.HasPrefix(path, "//") {
    44  		path = path[1:]
    45  	}
    46  
    47  	return URL{Addr: addr, User: user, Path: path}, nil
    48  }
    49  
    50  func parseUA(s string) (user, addr string, err error) {
    51  	switch {
    52  	case strings.Contains(s, "@"):
    53  		toks := strings.SplitN(s, "@", 2)
    54  		user = parseUser(toks[0])
    55  		addr = toks[1]
    56  	default:
    57  		addr = s
    58  	}
    59  
    60  	switch {
    61  	case strings.HasPrefix(addr, "["): // IPv6 literal
    62  		idx := strings.LastIndex(addr, "]")
    63  		col := strings.Index(addr[idx+1:], ":")
    64  		if col >= 0 {
    65  			_, _, err = net.SplitHostPort(addr)
    66  		}
    67  	case strings.Contains(addr, ":"):
    68  		_, _, err = net.SplitHostPort(addr)
    69  	}
    70  
    71  	if err != nil {
    72  		return "", "", fmt.Errorf("could not extract host+port from URI: %w", err)
    73  	}
    74  
    75  	return user, addr, nil
    76  }
    77  
    78  func parseUser(s string) string {
    79  	idx := strings.Index(s, ":")
    80  	if idx == -1 {
    81  		return s
    82  	}
    83  	return s[:idx]
    84  }