mirror of
https://github.com/minio/mc.git
synced 2025-11-13 12:22:45 +03:00
better args/url parssing
This commit is contained in:
3
Makefile
3
Makefile
@@ -60,7 +60,8 @@ docs-deploy:
|
|||||||
@mkdocs gh-deploy --clean
|
@mkdocs gh-deploy --clean
|
||||||
|
|
||||||
install: test-all
|
install: test-all
|
||||||
@godep go install github.com/minio-io/mc && echo "Installed mc:"
|
@echo "Installing mc:"
|
||||||
|
@godep go install github.com/minio-io/mc
|
||||||
@mkdir -p $(HOME)/.minio/mc
|
@mkdir -p $(HOME)/.minio/mc
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -227,12 +226,3 @@ func parseArgs(c *cli.Context) (args *cmdArgs, err error) {
|
|||||||
func getMcBashCompletionFilename() string {
|
func getMcBashCompletionFilename() string {
|
||||||
return path.Join(getMcConfigDir(), "mc.bash_completion")
|
return path.Join(getMcConfigDir(), "mc.bash_completion")
|
||||||
}
|
}
|
||||||
|
|
||||||
func isValidURL(s string) bool {
|
|
||||||
var r = "http.*://*"
|
|
||||||
ok, err := regexp.MatchString(r, s)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -152,12 +152,24 @@ func saveConfig(c *cli.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer configFile.Close()
|
|
||||||
|
|
||||||
_, err = configFile.Write(jsonConfig)
|
_, err = configFile.Write(jsonConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
configFile.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configFile.Close()
|
||||||
|
|
||||||
|
// Invalidate cached config
|
||||||
|
_config = nil
|
||||||
|
|
||||||
|
// Reload and cache new config
|
||||||
|
_, err = getMcConfig()
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,15 +86,12 @@ func listObjectPrefix(s3c client.Client, bucketName, objectName string, maxkeys
|
|||||||
func doListCmd(c *cli.Context) {
|
func doListCmd(c *cli.Context) {
|
||||||
var items []*client.Item
|
var items []*client.Item
|
||||||
// quiet := c.GlobalBool("quiet")
|
// quiet := c.GlobalBool("quiet")
|
||||||
urlStr, err := parseURL(c)
|
|
||||||
|
urlStr, err := parseURL(c.Args().First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal(err.Error())
|
fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isValidURL(urlStr) {
|
|
||||||
fatal(errInvalidScheme.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
bucketName, objectName, err := url2Object(urlStr)
|
bucketName, objectName, err := url2Object(urlStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal(err.Error())
|
fatal(err.Error())
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import (
|
|||||||
|
|
||||||
// doMakeBucketCmd creates a new bucket
|
// doMakeBucketCmd creates a new bucket
|
||||||
func doMakeBucketCmd(c *cli.Context) {
|
func doMakeBucketCmd(c *cli.Context) {
|
||||||
urlStr, err := parseURL(c)
|
urlStr, err := parseURL(c.Args().First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal(err.Error())
|
fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,15 @@ var (
|
|||||||
// fs
|
// fs
|
||||||
errFskey = errors.New("Key is needed to get the file")
|
errFskey = errors.New("Key is needed to get the file")
|
||||||
|
|
||||||
|
// url
|
||||||
|
errEmptyURL = errors.New("URL is empty")
|
||||||
|
|
||||||
// url
|
// url
|
||||||
errInvalidScheme = errors.New("Invalid URL scheme only http{s}:// supported")
|
errInvalidScheme = errors.New("Invalid URL scheme only http{s}:// supported")
|
||||||
|
|
||||||
|
// url
|
||||||
|
errInvalidURL = errors.New("Invalid URL")
|
||||||
|
|
||||||
// host
|
// host
|
||||||
errHostname = errors.New("No hostname specified")
|
errHostname = errors.New("No hostname specified")
|
||||||
|
|
||||||
|
|||||||
119
url-parser.go
119
url-parser.go
@@ -24,11 +24,99 @@ import (
|
|||||||
"github.com/minio-io/cli"
|
"github.com/minio-io/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// URLType defines supported storage protocols
|
||||||
|
type urlType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
urlUnknown urlType = iota // Minio and S3 compatible object storage
|
||||||
|
urlS3 // Minio and S3 compatible object storage
|
||||||
|
urlDonut // Donut object storage
|
||||||
|
urlFile // POSIX compatible file systems
|
||||||
|
)
|
||||||
|
|
||||||
|
// urlType detects the type of URL
|
||||||
|
func getURLType(urlStr string) (uType urlType, err error) {
|
||||||
|
u, err := url.Parse(urlStr)
|
||||||
|
if err != nil {
|
||||||
|
return urlUnknown, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch u.Scheme {
|
||||||
|
case "http":
|
||||||
|
fallthrough
|
||||||
|
case "https":
|
||||||
|
return urlS3, nil
|
||||||
|
case "donut":
|
||||||
|
return urlDonut, nil
|
||||||
|
case "file":
|
||||||
|
fallthrough
|
||||||
|
case "":
|
||||||
|
return urlFile, nil
|
||||||
|
default:
|
||||||
|
return urlUnknown, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// isValidURL checks the validity of supported URL types
|
||||||
|
func isValidURL(urlStr string) bool {
|
||||||
|
u, e := getURLType(urlStr)
|
||||||
|
if e != nil || u == urlUnknown {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// isValidURL checks the validity of supported URL types
|
||||||
|
func isValidFileURL(urlStr string) bool {
|
||||||
|
u, e := getURLType(urlStr)
|
||||||
|
if e != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if u != urlFile {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixFileURL rewrites file URL to proper file:///path/to/ form.
|
||||||
|
func fixFileURL(urlStr string) (fixedURL string, err error) {
|
||||||
|
ut, e := getURLType(urlStr)
|
||||||
|
if e != nil || ut != urlFile {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
|
||||||
|
if urlStr == "" {
|
||||||
|
return "", errEmptyURL
|
||||||
|
}
|
||||||
|
|
||||||
|
u, e := url.Parse(urlStr)
|
||||||
|
if e != nil {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
|
||||||
|
// file:///path should always have empty host
|
||||||
|
if u.Host != "" {
|
||||||
|
// Not really a file URL. Host is not empty.
|
||||||
|
return "", errInvalidURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill missing scheme
|
||||||
|
if u.Scheme == "" {
|
||||||
|
// Set it to file
|
||||||
|
u.Scheme = "file"
|
||||||
|
}
|
||||||
|
|
||||||
|
fixedURL = u.String()
|
||||||
|
return fixedURL, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// url2Object converts URL to bucket and objectname
|
// url2Object converts URL to bucket and objectname
|
||||||
func url2Object(urlStr string) (bucketName, objectName string, err error) {
|
func url2Object(urlStr string) (bucketName, objectName string, err error) {
|
||||||
url, err := url.Parse(urlStr)
|
url, err := url.Parse(urlStr)
|
||||||
if url.Path == "" {
|
if url.Path == "" {
|
||||||
// No bucket name passed. It is a valid case.
|
// No bucket name passed. It is a valid case
|
||||||
return "", "", nil
|
return "", "", nil
|
||||||
}
|
}
|
||||||
splits := strings.SplitN(url.Path, "/", 3)
|
splits := strings.SplitN(url.Path, "/", 3)
|
||||||
@@ -53,8 +141,9 @@ func url2Bucket(urlStr string) (bucketName string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseURL extracts URL string from a single cmd-line argument
|
// parseURL extracts URL string from a single cmd-line argument
|
||||||
func parseURL(c *cli.Context) (urlStr string, err error) {
|
func parseURL(arg string) (urlStr string, err error) {
|
||||||
urlStr = c.Args().First()
|
urlStr = arg
|
||||||
|
|
||||||
// Use default host if no argument is passed
|
// Use default host if no argument is passed
|
||||||
if urlStr == "" {
|
if urlStr == "" {
|
||||||
// Load config file
|
// Load config file
|
||||||
@@ -64,12 +153,34 @@ func parseURL(c *cli.Context) (urlStr string, err error) {
|
|||||||
}
|
}
|
||||||
urlStr = config.DefaultHost
|
urlStr = config.DefaultHost
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check and expand Alias
|
// Check and expand Alias
|
||||||
urlStr, err = aliasExpand(urlStr)
|
urlStr, err = aliasExpand(urlStr)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !isValidURL(urlStr) {
|
||||||
|
return "", errInvalidScheme
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is a file URL, rewrite to file:///path/to form
|
||||||
|
if isValidFileURL(urlStr) {
|
||||||
|
urlStr, err = fixFileURL(urlStr)
|
||||||
|
return urlStr, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return urlStr, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseURL extracts multiple URL strings from a single cmd-line argument
|
||||||
|
func parseURLs(c *cli.Context) (urlStr []string, err error) {
|
||||||
|
for _, arg := range c.Args() {
|
||||||
|
u, err := parseURL(arg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
urlStr = append(urlStr, u)
|
||||||
|
}
|
||||||
return urlStr, err
|
return urlStr, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user