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