Home | History | Annotate | Download | only in go
      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) }
    121