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