github.com/sirkon/goproxy@v1.4.8/mod_info.go (about)

     1  package goproxy
     2  
     3  import (
     4  	"net/http"
     5  	"strings"
     6  
     7  	"github.com/sirkon/goproxy/internal/errors"
     8  
     9  	"github.com/sirkon/goproxy/internal/module"
    10  )
    11  
    12  const (
    13  	slashDogVSlash      = "/@v/"
    14  	constSlashDogLatest = "/@latest"
    15  )
    16  
    17  // modInfoExtraction ...
    18  type modInfoExtraction struct {
    19  	Rest   string
    20  	Module string
    21  	Suffix string
    22  }
    23  
    24  // Extract ...
    25  func (p *modInfoExtraction) Extract(line string) (bool, error) {
    26  	p.Rest = line
    27  	var pos int
    28  
    29  	// Checks if the rest starts with '/' and pass it
    30  	if len(p.Rest) >= 1 && p.Rest[0] == '/' {
    31  		p.Rest = p.Rest[1:]
    32  	} else {
    33  		return false, errors.Newf("/<url> expected, got %s", line)
    34  	}
    35  
    36  	// Take until "/@v/" as Module(string)
    37  	pos = strings.Index(p.Rest, slashDogVSlash)
    38  	if pos >= 0 {
    39  		p.Module = p.Rest[:pos]
    40  		p.Rest = p.Rest[pos+len(slashDogVSlash):]
    41  	} else {
    42  		return false, errors.Newf("/@v/ was not found in %s", p.Rest)
    43  	}
    44  
    45  	// Take the rest as Suffix(string)
    46  	p.Suffix = p.Rest
    47  	p.Rest = p.Rest[len(p.Rest):]
    48  	return true, nil
    49  }
    50  
    51  // latestExtraction ...
    52  type latestExtraction struct {
    53  	Rest string
    54  	Path string
    55  }
    56  
    57  // Extract ...
    58  func (p *latestExtraction) Extract(line string) (bool, error) {
    59  	p.Rest = line
    60  	var pos int
    61  
    62  	// Checks if the rest starts with '/' and pass it
    63  	if len(p.Rest) >= 1 && p.Rest[0] == '/' {
    64  		p.Rest = p.Rest[1:]
    65  	} else {
    66  		return false, nil
    67  	}
    68  
    69  	// Take until "/@latest" as Path(string)
    70  	pos = strings.Index(p.Rest, constSlashDogLatest)
    71  	if pos >= 0 {
    72  		p.Path = p.Rest[:pos]
    73  		p.Rest = p.Rest[pos+len(constSlashDogLatest):]
    74  	} else {
    75  		return false, nil
    76  	}
    77  
    78  	return true, nil
    79  }
    80  
    81  // GetModInfo retrieves mod info from URL
    82  func GetModInfo(req *http.Request, prefix string) (path string, suffix string, err error) {
    83  	method := req.URL.Path
    84  	if !strings.HasPrefix(method, prefix) {
    85  		err = errors.Newf("request URL path expected to be a %s*, got %s", prefix, method)
    86  	}
    87  	method = method[len(prefix):]
    88  
    89  	var ok bool
    90  	var le latestExtraction
    91  	var e modInfoExtraction
    92  
    93  	if ok, _ = le.Extract(method); ok {
    94  		path = le.Path
    95  		suffix = "latest"
    96  
    97  	} else if ok, err = e.Extract(method); ok {
    98  		path = e.Module
    99  		suffix = e.Suffix
   100  	} else {
   101  		err = errors.Wrapf(err, "invalid go proxy request, wrong URL %s", method)
   102  		return
   103  	}
   104  
   105  	path, err = module.DecodePath(path)
   106  	if err != nil {
   107  		return
   108  	}
   109  
   110  	return
   111  }
   112  
   113  // PathEncoding returns go module encoded path
   114  func PathEncoding(path string) (string, error) {
   115  	return module.EncodePath(path)
   116  }