github.com/bir3/gocompiler@v0.9.2202/src/cmd/gocmd/internal/web/url.go (about) 1 // Copyright 2019 The Go 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 web 6 7 import ( 8 "errors" 9 "net/url" 10 "path/filepath" 11 "strings" 12 ) 13 14 // TODO(golang.org/issue/32456): If accepted, move these functions into the 15 // net/url package. 16 17 var errNotAbsolute = errors.New("path is not absolute") 18 19 func urlToFilePath(u *url.URL) (string, error) { 20 if u.Scheme != "file" { 21 return "", errors.New("non-file URL") 22 } 23 24 checkAbs := func(path string) (string, error) { 25 if !filepath.IsAbs(path) { 26 return "", errNotAbsolute 27 } 28 return path, nil 29 } 30 31 if u.Path == "" { 32 if u.Host != "" || u.Opaque == "" { 33 return "", errors.New("file URL missing path") 34 } 35 return checkAbs(filepath.FromSlash(u.Opaque)) 36 } 37 38 path, err := convertFileURLPath(u.Host, u.Path) 39 if err != nil { 40 return path, err 41 } 42 return checkAbs(path) 43 } 44 45 func urlFromFilePath(path string) (*url.URL, error) { 46 if !filepath.IsAbs(path) { 47 return nil, errNotAbsolute 48 } 49 50 // If path has a Windows volume name, convert the volume to a host and prefix 51 // per https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/. 52 if vol := filepath.VolumeName(path); vol != "" { 53 if strings.HasPrefix(vol, `\\`) { 54 path = filepath.ToSlash(path[2:]) 55 i := strings.IndexByte(path, '/') 56 57 if i < 0 { 58 // A degenerate case. 59 // \\host.example.com (without a share name) 60 // becomes 61 // file://host.example.com/ 62 return &url.URL{ 63 Scheme: "file", 64 Host: path, 65 Path: "/", 66 }, nil 67 } 68 69 // \\host.example.com\Share\path\to\file 70 // becomes 71 // file://host.example.com/Share/path/to/file 72 return &url.URL{ 73 Scheme: "file", 74 Host: path[:i], 75 Path: filepath.ToSlash(path[i:]), 76 }, nil 77 } 78 79 // C:\path\to\file 80 // becomes 81 // file:///C:/path/to/file 82 return &url.URL{ 83 Scheme: "file", 84 Path: "/" + filepath.ToSlash(path), 85 }, nil 86 } 87 88 // /path/to/file 89 // becomes 90 // file:///path/to/file 91 return &url.URL{ 92 Scheme: "file", 93 Path: filepath.ToSlash(path), 94 }, nil 95 }