forked from golang/gddo
/
client.go
124 lines (115 loc) · 2.61 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright 2013 The Go Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd.
package gosrc
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
)
type httpClient struct {
errFn func(*http.Response) error
header http.Header
client *http.Client
}
func (c *httpClient) err(resp *http.Response) error {
if resp.StatusCode == 404 {
return NotFoundError{"Resource not found: " + resp.Request.URL.String()}
}
if c.errFn != nil {
return c.errFn(resp)
}
return &RemoteError{resp.Request.URL.Host, fmt.Errorf("%d: (%s)", resp.StatusCode, resp.Request.URL.String())}
}
func (c *httpClient) get(url string) (*http.Response, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
for k, vs := range c.header {
req.Header[k] = vs
}
resp, err := c.client.Do(req)
if err != nil {
return nil, &RemoteError{req.URL.Host, err}
}
return resp, err
}
func (c *httpClient) getBytes(url string) ([]byte, error) {
resp, err := c.get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, c.err(resp)
}
p, err := ioutil.ReadAll(resp.Body)
return p, err
}
func (c *httpClient) getReader(url string) (io.ReadCloser, error) {
resp, err := c.get(url)
if err != nil {
return nil, err
}
if resp.StatusCode != 200 {
err = c.err(resp)
resp.Body.Close()
return nil, err
}
return resp.Body, nil
}
func (c *httpClient) getJSON(url string, v interface{}) error {
resp, err := c.get(url)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return c.err(resp)
}
err = json.NewDecoder(resp.Body).Decode(v)
if _, ok := err.(*json.SyntaxError); ok {
err = NotFoundError{"JSON syntax error at " + url}
}
return err
}
func (c *httpClient) getFiles(urls []string, files []*File) error {
ch := make(chan error, len(files))
for i := range files {
go func(i int) {
resp, err := c.get(urls[i])
if err != nil {
ch <- err
return
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
var err error
if c.errFn != nil {
err = c.errFn(resp)
} else {
err = &RemoteError{resp.Request.URL.Host, fmt.Errorf("get %s -> %d", urls[i], resp.StatusCode)}
}
ch <- err
return
}
files[i].Data, err = ioutil.ReadAll(resp.Body)
if err != nil {
ch <- &RemoteError{resp.Request.URL.Host, err}
return
}
ch <- nil
}(i)
}
for _ = range files {
if err := <-ch; err != nil {
return err
}
}
return nil
}