github.com/freddyisaac/sicortex-golang@v0.0.0-20231019035217-e03519e66f60/src/cmd/pprof/internal/fetch/fetch.go (about)

     1  // Copyright 2014 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 fetch provides an extensible mechanism to fetch a profile
     6  // from a data source.
     7  package fetch
     8  
     9  import (
    10  	"crypto/tls"
    11  	"fmt"
    12  	"io"
    13  	"io/ioutil"
    14  	"net/http"
    15  	"net/url"
    16  	"os"
    17  	"strings"
    18  	"time"
    19  
    20  	"cmd/pprof/internal/plugin"
    21  	"internal/pprof/profile"
    22  )
    23  
    24  // FetchProfile reads from a data source (network, file) and generates a
    25  // profile.
    26  func FetchProfile(source string, timeout time.Duration) (*profile.Profile, error) {
    27  	return Fetcher(source, timeout, plugin.StandardUI())
    28  }
    29  
    30  // Fetcher is the plugin.Fetcher version of FetchProfile.
    31  func Fetcher(source string, timeout time.Duration, ui plugin.UI) (*profile.Profile, error) {
    32  	var f io.ReadCloser
    33  	var err error
    34  
    35  	url, err := url.Parse(source)
    36  	if err == nil && url.Host != "" {
    37  		f, err = FetchURL(source, timeout)
    38  	} else {
    39  		f, err = os.Open(source)
    40  	}
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	defer f.Close()
    45  	return profile.Parse(f)
    46  }
    47  
    48  // FetchURL fetches a profile from a URL using HTTP.
    49  func FetchURL(source string, timeout time.Duration) (io.ReadCloser, error) {
    50  	resp, err := httpGet(source, timeout)
    51  	if err != nil {
    52  		return nil, fmt.Errorf("http fetch %s: %v", source, err)
    53  	}
    54  	if resp.StatusCode != http.StatusOK {
    55  		return nil, fmt.Errorf("server response: %s", resp.Status)
    56  	}
    57  
    58  	return resp.Body, nil
    59  }
    60  
    61  // PostURL issues a POST to a URL over HTTP.
    62  func PostURL(source, post string) ([]byte, error) {
    63  	resp, err := http.Post(source, "application/octet-stream", strings.NewReader(post))
    64  	if err != nil {
    65  		return nil, fmt.Errorf("http post %s: %v", source, err)
    66  	}
    67  	if resp.StatusCode != http.StatusOK {
    68  		return nil, fmt.Errorf("server response: %s", resp.Status)
    69  	}
    70  	defer resp.Body.Close()
    71  	return ioutil.ReadAll(resp.Body)
    72  }
    73  
    74  // httpGet is a wrapper around http.Get; it is defined as a variable
    75  // so it can be redefined during for testing.
    76  var httpGet = func(source string, timeout time.Duration) (*http.Response, error) {
    77  	url, err := url.Parse(source)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  
    82  	var tlsConfig *tls.Config
    83  	if url.Scheme == "https+insecure" {
    84  		tlsConfig = &tls.Config{
    85  			InsecureSkipVerify: true,
    86  		}
    87  		url.Scheme = "https"
    88  		source = url.String()
    89  	}
    90  
    91  	client := &http.Client{
    92  		Transport: &http.Transport{
    93  			ResponseHeaderTimeout: timeout + 5*time.Second,
    94  			TLSClientConfig:       tlsConfig,
    95  		},
    96  	}
    97  	return client.Get(source)
    98  }