LEFT | RIGHT |
(no file at all) | |
| 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.Profi
le, 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.NewRe
ader(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 } |
LEFT | RIGHT |