github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/vndr/godl/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  package godl
     6  
     7  import (
     8  	"fmt"
     9  	"io"
    10  	"io/ioutil"
    11  	"net/http"
    12  	"net/url"
    13  	"time"
    14  )
    15  
    16  // httpClient is the default HTTP client, but a variable so it can be
    17  // changed by tests, without modifying http.DefaultClient.
    18  var httpClient = http.DefaultClient
    19  var impatientHTTPClient = &http.Client{
    20  	Timeout: time.Duration(5 * time.Second),
    21  }
    22  
    23  type httpError struct {
    24  	status     string
    25  	statusCode int
    26  	url        string
    27  }
    28  
    29  func (e *httpError) Error() string {
    30  	return fmt.Sprintf("%s: %s", e.url, e.status)
    31  }
    32  
    33  // httpGET returns the data from an HTTP GET request for the given URL.
    34  func httpGET(url string) ([]byte, error) {
    35  	resp, err := httpClient.Get(url)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	defer resp.Body.Close()
    40  	if resp.StatusCode != 200 {
    41  		err := &httpError{status: resp.Status, statusCode: resp.StatusCode, url: url}
    42  
    43  		return nil, err
    44  	}
    45  	b, err := ioutil.ReadAll(resp.Body)
    46  	if err != nil {
    47  		return nil, fmt.Errorf("%s: %v", url, err)
    48  	}
    49  	return b, nil
    50  }
    51  
    52  // httpsOrHTTP returns the body of either the importPath's
    53  // https resource or, if unavailable, the http resource.
    54  func httpsOrHTTP(importPath string, security securityMode) (urlStr string, body io.ReadCloser, err error) {
    55  	fetch := func(scheme string) (urlStr string, res *http.Response, err error) {
    56  		u, err := url.Parse(scheme + "://" + importPath)
    57  		if err != nil {
    58  			return "", nil, err
    59  		}
    60  		u.RawQuery = "go-get=1"
    61  		urlStr = u.String()
    62  		if security == insecure && scheme == "https" { // fail earlier
    63  			res, err = impatientHTTPClient.Get(urlStr)
    64  		} else {
    65  			res, err = httpClient.Get(urlStr)
    66  		}
    67  		return
    68  	}
    69  	closeBody := func(res *http.Response) {
    70  		if res != nil {
    71  			res.Body.Close()
    72  		}
    73  	}
    74  	urlStr, res, err := fetch("https")
    75  	if err != nil {
    76  		if security == insecure {
    77  			closeBody(res)
    78  			urlStr, res, err = fetch("http")
    79  		}
    80  	}
    81  	if err != nil {
    82  		closeBody(res)
    83  		return "", nil, err
    84  	}
    85  	// Note: accepting a non-200 OK here, so people can serve a
    86  	// meta import in their http 404 page.
    87  	return urlStr, res.Body, nil
    88  }