|
- // 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{Message: "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())}
- }
-
- // get issues a GET to the specified URL.
- 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
- }
-
- // getNoFollow issues a GET to the specified URL without following redirects.
- func (c *httpClient) getNoFollow(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
- }
- t := c.client.Transport
- if t == nil {
- t = http.DefaultTransport
- }
- resp, err := t.RoundTrip(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{}) (*http.Response, error) {
- resp, err := c.get(url)
- if err != nil {
- return resp, err
- }
- defer resp.Body.Close()
- if resp.StatusCode != 200 {
- return resp, c.err(resp)
- }
- err = json.NewDecoder(resp.Body).Decode(v)
- if _, ok := err.(*json.SyntaxError); ok {
- err = NotFoundError{Message: "JSON syntax error at " + url}
- }
- return resp, 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
- }
|