Source file src/cmd/go/internal/web/url.go

     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  }
    96  

View as plain text