mirror of
https://github.com/dutchcoders/transfer.sh.git
synced 2025-01-09 10:30:19 +01:00
146 lines
3.2 KiB
Go
146 lines
3.2 KiB
Go
|
// 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
|
||
|
}
|