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