github.com/uber/kraken@v0.1.4/lib/backend/httpbackend/http.go (about) 1 // Copyright (c) 2016-2019 Uber Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 package httpbackend 15 16 import ( 17 "bytes" 18 "errors" 19 "fmt" 20 "io" 21 "time" 22 23 "github.com/uber/kraken/core" 24 "github.com/uber/kraken/lib/backend" 25 "github.com/uber/kraken/lib/backend/backenderrors" 26 "github.com/uber/kraken/utils/httputil" 27 28 "gopkg.in/yaml.v2" 29 ) 30 31 const _http = "http" 32 33 func init() { 34 backend.Register(_http, &factory{}) 35 } 36 37 type factory struct{} 38 39 func (f *factory) Create( 40 confRaw interface{}, authConfRaw interface{}) (backend.Client, error) { 41 42 confBytes, err := yaml.Marshal(confRaw) 43 if err != nil { 44 return nil, errors.New("marshal http config") 45 } 46 47 var config Config 48 if err := yaml.Unmarshal(confBytes, &config); err != nil { 49 return nil, errors.New("unmarshal http config") 50 } 51 return NewClient(config) 52 } 53 54 // Config defines http post/get upload/download urls 55 // and http connnection parameters. The URLs come with string format 56 // specifiers and define how to pass sha256 parameters 57 type Config struct { 58 UploadURL string `yaml:"upload_url"` // http upload post url 59 DownloadURL string `yaml:"download_url"` // http download get url 60 DownloadTimeout time.Duration `yaml:"download_timeout"` 61 DownloadBackOff httputil.ExponentialBackOffConfig `yaml:"download_backoff"` 62 } 63 64 // Client implements downloading/uploading object from/to S3 65 type Client struct { 66 config Config 67 } 68 69 func (c Config) applyDefaults() Config { 70 if c.DownloadTimeout == 0 { 71 c.DownloadTimeout = 180 * time.Second 72 } 73 return c 74 } 75 76 // NewClient creates a new http Client. 77 func NewClient(config Config) (*Client, error) { 78 return &Client{config: config.applyDefaults()}, nil 79 } 80 81 // Stat always succeeds. 82 // TODO(codyg): Support stat URL. 83 func (c *Client) Stat(namespace, name string) (*core.BlobInfo, error) { 84 return core.NewBlobInfo(0), nil 85 } 86 87 // Download downloads the content from a configured url and writes the data 88 // to dst. 89 func (c *Client) Download(namespace, name string, dst io.Writer) error { 90 // Use Fprintf instead of Sprintf to handle formatting errors. 91 var b bytes.Buffer 92 if _, err := fmt.Fprintf(&b, c.config.DownloadURL, name); err != nil { 93 return fmt.Errorf("format url: %s", err) 94 } 95 resp, err := httputil.Get( 96 b.String(), 97 httputil.SendTimeout(c.config.DownloadTimeout), 98 httputil.SendRetry(httputil.RetryBackoff(c.config.DownloadBackOff.Build()))) 99 if err != nil { 100 if httputil.IsNotFound(err) { 101 return backenderrors.ErrBlobNotFound 102 } 103 return err 104 } 105 defer resp.Body.Close() 106 if _, err := io.Copy(dst, resp.Body); err != nil { 107 return fmt.Errorf("copy: %s", err) 108 } 109 return nil 110 } 111 112 // Upload is not supported. 113 func (c *Client) Upload(namespace, name string, src io.Reader) error { 114 return errors.New("not supported") 115 } 116 117 // List is not supported. 118 func (c *Client) List(prefix string, opts ...backend.ListOption) (*backend.ListResult, error) { 119 return nil, errors.New("not supported") 120 }