Created
April 20, 2021 16:23
-
-
Save angelbarrera92/7868087f3f7a995a9ff340e98a41d8dc to your computer and use it in GitHub Desktop.
golang download parsing netrc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"io" | |
"io/ioutil" | |
"net/http" | |
"net/url" | |
"os" | |
"strings" | |
) | |
func main() { | |
downloadFile("https://github.com/sighupio/furyctl-provisioners/archive/vsphere.zip", "/tmp/vsphere.zip", "/Users/angelbarrerasanchez-sighup/work/sighup/furyctl/demo/bootstrap/configuration/.netrc") | |
} | |
func downloadFile(fileURL string, filepath string, netrcfile string) error { | |
data, err := ioutil.ReadFile(netrcfile) | |
authMap := parseNetrc(string(data)) | |
u, err := url.Parse(fileURL) | |
if err != nil { | |
panic(err) | |
} | |
// Looking for the right user and password | |
auth := authMap[u.Host] | |
client := &http.Client{} | |
req, err := http.NewRequest("GET", fileURL, nil) | |
req.SetBasicAuth(auth.login, auth.password) | |
resp, err := client.Do(req) | |
// // Get the data | |
if err != nil { | |
return err | |
} | |
defer resp.Body.Close() | |
// Create the file | |
out, err := os.Create(filepath) | |
if err != nil { | |
return err | |
} | |
defer out.Close() | |
// Write the body to file | |
_, err = io.Copy(out, resp.Body) | |
return err | |
} | |
// The following functions were extracted from src/cmd/go/internal/web2/web.go | |
// as of https://golang.org/cl/161698. | |
type netrcLine struct { | |
machine string | |
login string | |
password string | |
} | |
func parseNetrc(data string) map[string]netrcLine { | |
// See https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html | |
// for documentation on the .netrc format. | |
m := make(map[string]netrcLine) | |
var l netrcLine | |
inMacro := false | |
for _, line := range strings.Split(data, "\n") { | |
if inMacro { | |
if line == "" { | |
inMacro = false | |
} | |
continue | |
} | |
f := strings.Fields(line) | |
i := 0 | |
for ; i < len(f)-1; i += 2 { | |
// Reset at each "machine" token. | |
// “The auto-login process searches the .netrc file for a machine token | |
// that matches […]. Once a match is made, the subsequent .netrc tokens | |
// are processed, stopping when the end of file is reached or another | |
// machine or a default token is encountered.” | |
switch f[i] { | |
case "machine": | |
l = netrcLine{machine: f[i+1]} | |
case "default": | |
break | |
case "login": | |
l.login = f[i+1] | |
case "password": | |
l.password = f[i+1] | |
case "macdef": | |
// “A macro is defined with the specified name; its contents begin with | |
// the next .netrc line and continue until a null line (consecutive | |
// new-line characters) is encountered.” | |
inMacro = true | |
} | |
if l.machine != "" && l.login != "" && l.password != "" { | |
m[l.machine] = l | |
l = netrcLine{} | |
} | |
} | |
if i < len(f) && f[i] == "default" { | |
// “There can be only one default token, and it must be after all machine tokens.” | |
break | |
} | |
} | |
return m | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment