golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/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) }