aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/cmd/go/internal/web/http.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/cmd/go/internal/web/http.go')
-rw-r--r--libgo/go/cmd/go/internal/web/http.go122
1 files changed, 122 insertions, 0 deletions
diff --git a/libgo/go/cmd/go/internal/web/http.go b/libgo/go/cmd/go/internal/web/http.go
new file mode 100644
index 00000000000..6e347fbf860
--- /dev/null
+++ b/libgo/go/cmd/go/internal/web/http.go
@@ -0,0 +1,122 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !cmd_go_bootstrap
+
+// This code is compiled into the real 'go' binary, but it is not
+// compiled into the binary that is built during all.bash, so as
+// to avoid needing to build net (and thus use cgo) during the
+// bootstrap process.
+
+package web
+
+import (
+ "crypto/tls"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "net/url"
+ "time"
+
+ "cmd/go/internal/cfg"
+ "cmd/internal/browser"
+)
+
+// httpClient is the default HTTP client, but a variable so it can be
+// changed by tests, without modifying http.DefaultClient.
+var httpClient = http.DefaultClient
+
+// impatientInsecureHTTPClient is used in -insecure mode,
+// when we're connecting to https servers that might not be there
+// or might be using self-signed certificates.
+var impatientInsecureHTTPClient = &http.Client{
+ Timeout: 5 * time.Second,
+ Transport: &http.Transport{
+ Proxy: http.ProxyFromEnvironment,
+ TLSClientConfig: &tls.Config{
+ InsecureSkipVerify: true,
+ },
+ },
+}
+
+type HTTPError struct {
+ status string
+ StatusCode int
+ url string
+}
+
+func (e *HTTPError) Error() string {
+ return fmt.Sprintf("%s: %s", e.url, e.status)
+}
+
+// Get returns the data from an HTTP GET request for the given URL.
+func Get(url string) ([]byte, error) {
+ resp, err := httpClient.Get(url)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != 200 {
+ err := &HTTPError{status: resp.Status, StatusCode: resp.StatusCode, url: url}
+
+ return nil, err
+ }
+ b, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, fmt.Errorf("%s: %v", url, err)
+ }
+ return b, nil
+}
+
+// GetMaybeInsecure returns the body of either the importPath's
+// https resource or, if unavailable and permitted by the security mode, the http resource.
+func GetMaybeInsecure(importPath string, security SecurityMode) (urlStr string, body io.ReadCloser, err error) {
+ fetch := func(scheme string) (urlStr string, res *http.Response, err error) {
+ u, err := url.Parse(scheme + "://" + importPath)
+ if err != nil {
+ return "", nil, err
+ }
+ u.RawQuery = "go-get=1"
+ urlStr = u.String()
+ if cfg.BuildV {
+ log.Printf("Fetching %s", urlStr)
+ }
+ if security == Insecure && scheme == "https" { // fail earlier
+ res, err = impatientInsecureHTTPClient.Get(urlStr)
+ } else {
+ res, err = httpClient.Get(urlStr)
+ }
+ return
+ }
+ closeBody := func(res *http.Response) {
+ if res != nil {
+ res.Body.Close()
+ }
+ }
+ urlStr, res, err := fetch("https")
+ if err != nil {
+ if cfg.BuildV {
+ log.Printf("https fetch failed: %v", err)
+ }
+ if security == Insecure {
+ closeBody(res)
+ urlStr, res, err = fetch("http")
+ }
+ }
+ if err != nil {
+ closeBody(res)
+ return "", nil, err
+ }
+ // Note: accepting a non-200 OK here, so people can serve a
+ // meta import in their http 404 page.
+ if cfg.BuildV {
+ log.Printf("Parsing meta tags from %s (status code %d)", urlStr, res.StatusCode)
+ }
+ return urlStr, res.Body, nil
+}
+
+func QueryEscape(s string) string { return url.QueryEscape(s) }
+func OpenBrowser(url string) bool { return browser.Open(url) }