github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/cmd/go/internal/web/http.go (about) 1 // Copyright 2012 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 // +build !cmd_go_bootstrap 6 7 // This code is compiled into the real 'go' binary, but it is not 8 // compiled into the binary that is built during all.bash, so as 9 // to avoid needing to build net (and thus use cgo) during the 10 // bootstrap process. 11 12 package web 13 14 import ( 15 "crypto/tls" 16 "fmt" 17 "io" 18 "io/ioutil" 19 "log" 20 "net/http" 21 "net/url" 22 "time" 23 24 "cmd/go/internal/cfg" 25 "cmd/internal/browser" 26 ) 27 28 // httpClient is the default HTTP client, but a variable so it can be 29 // changed by tests, without modifying http.DefaultClient. 30 var httpClient = http.DefaultClient 31 32 // impatientInsecureHTTPClient is used in -insecure mode, 33 // when we're connecting to https servers that might not be there 34 // or might be using self-signed certificates. 35 var impatientInsecureHTTPClient = &http.Client{ 36 Timeout: 5 * time.Second, 37 Transport: &http.Transport{ 38 Proxy: http.ProxyFromEnvironment, 39 TLSClientConfig: &tls.Config{ 40 InsecureSkipVerify: true, 41 }, 42 }, 43 } 44 45 type HTTPError struct { 46 status string 47 StatusCode int 48 url string 49 } 50 51 func (e *HTTPError) Error() string { 52 return fmt.Sprintf("%s: %s", e.url, e.status) 53 } 54 55 // Get returns the data from an HTTP GET request for the given URL. 56 func Get(url string) ([]byte, error) { 57 resp, err := httpClient.Get(url) 58 if err != nil { 59 return nil, err 60 } 61 defer resp.Body.Close() 62 if resp.StatusCode != 200 { 63 err := &HTTPError{status: resp.Status, StatusCode: resp.StatusCode, url: url} 64 65 return nil, err 66 } 67 b, err := ioutil.ReadAll(resp.Body) 68 if err != nil { 69 return nil, fmt.Errorf("%s: %v", url, err) 70 } 71 return b, nil 72 } 73 74 // GetMaybeInsecure returns the body of either the importPath's 75 // https resource or, if unavailable and permitted by the security mode, the http resource. 76 func GetMaybeInsecure(importPath string, security SecurityMode) (urlStr string, body io.ReadCloser, err error) { 77 fetch := func(scheme string) (urlStr string, res *http.Response, err error) { 78 u, err := url.Parse(scheme + "://" + importPath) 79 if err != nil { 80 return "", nil, err 81 } 82 u.RawQuery = "go-get=1" 83 urlStr = u.String() 84 if cfg.BuildV { 85 log.Printf("Fetching %s", urlStr) 86 } 87 if security == Insecure && scheme == "https" { // fail earlier 88 res, err = impatientInsecureHTTPClient.Get(urlStr) 89 } else { 90 res, err = httpClient.Get(urlStr) 91 } 92 return 93 } 94 closeBody := func(res *http.Response) { 95 if res != nil { 96 res.Body.Close() 97 } 98 } 99 urlStr, res, err := fetch("https") 100 if err != nil { 101 if cfg.BuildV { 102 log.Printf("https fetch failed: %v", err) 103 } 104 if security == Insecure { 105 closeBody(res) 106 urlStr, res, err = fetch("http") 107 } 108 } 109 if err != nil { 110 closeBody(res) 111 return "", nil, err 112 } 113 // Note: accepting a non-200 OK here, so people can serve a 114 // meta import in their http 404 page. 115 if cfg.BuildV { 116 log.Printf("Parsing meta tags from %s (status code %d)", urlStr, res.StatusCode) 117 } 118 return urlStr, res.Body, nil 119 } 120 121 func QueryEscape(s string) string { return url.QueryEscape(s) } 122 func OpenBrowser(url string) bool { return browser.Open(url) }