github.com/everdrone/grab@v0.1.7-0.20230416223925-40674b995521/internal/utils/parse_urls.go (about)

     1  package utils
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/hcl/v2"
     9  )
    10  
    11  func ParseURLList(contents, filename string) ([]string, hcl.Diagnostics) {
    12  	urls := make([]string, 0)
    13  
    14  	lines := strings.Split(strings.ReplaceAll(contents, "\r\n", "\n"), "\n")
    15  
    16  	for i, line := range lines {
    17  		line = strings.TrimSpace(line)
    18  
    19  		if line == "" ||
    20  			strings.HasPrefix(line, "#") ||
    21  			strings.HasPrefix(line, "//") ||
    22  			strings.HasPrefix(line, ";") {
    23  			// ignore #, ;, // and empty lines
    24  			continue
    25  		}
    26  
    27  		// trim again in case the comment starts with a space
    28  		line = strings.TrimSpace(line)
    29  
    30  		url, err := url.Parse(line)
    31  		if err != nil || !url.IsAbs() {
    32  			return nil, hcl.Diagnostics{&hcl.Diagnostic{
    33  				Severity: hcl.DiagError,
    34  				Summary:  "Invalid URL",
    35  				Detail:   fmt.Sprintf("The string '%s' is not a valid url.", line),
    36  				Subject: &hcl.Range{
    37  					Filename: filename,
    38  					Start:    hcl.Pos{Line: i + 1, Column: 1},
    39  					End:      hcl.Pos{Line: i + 1, Column: len(line) + 1},
    40  				},
    41  			}}
    42  		}
    43  
    44  		// remove fragment
    45  		url.Fragment = ""
    46  		url.RawFragment = ""
    47  
    48  		urls = append(urls, url.String())
    49  	}
    50  
    51  	return urls, nil
    52  }
    53  
    54  func GetURLsFromArgs(args []string) ([]string, hcl.Diagnostics) {
    55  	urls := make([]string, 0)
    56  
    57  	for _, arg := range args {
    58  		if parsed, ok := IsValidURL(arg); ok {
    59  			// valid url, clean it up
    60  			parsed.Fragment = ""
    61  			parsed.RawFragment = ""
    62  
    63  			urls = append(urls, parsed.String())
    64  		} else {
    65  			// not valid, check if it's a file
    66  			absolute := Abs(arg)
    67  			exists, err := Io.Exists(Fs, absolute)
    68  			if err != nil || !exists {
    69  				return nil, hcl.Diagnostics{&hcl.Diagnostic{
    70  					Severity: hcl.DiagError,
    71  					Summary:  "Invalid argument",
    72  					Detail:   fmt.Sprintf("The argument '%s' is not a valid url, nor a file.", arg),
    73  				}}
    74  			}
    75  
    76  			// we got a file, parse it
    77  			fc, err := Io.ReadFile(Fs, absolute)
    78  			if err != nil {
    79  				return nil, hcl.Diagnostics{&hcl.Diagnostic{
    80  					Severity: hcl.DiagError,
    81  					Summary:  "Could not read file",
    82  					Detail:   fmt.Sprintf("Could not read file '%s'.", absolute),
    83  				}}
    84  			}
    85  
    86  			parsed, diags := ParseURLList(string(fc), absolute)
    87  			if diags.HasErrors() {
    88  				return nil, diags
    89  			}
    90  
    91  			urls = append(urls, parsed...)
    92  		}
    93  	}
    94  
    95  	return urls, nil
    96  }
    97  
    98  func IsValidURL(str string) (*url.URL, bool) {
    99  	u, err := url.Parse(str)
   100  	return u, err == nil && u.Scheme != "" && u.Host != ""
   101  }