diff --git a/webfile.go b/webfile.go index 58208e3..594b81c 100644 --- a/webfile.go +++ b/webfile.go @@ -26,23 +26,30 @@ func NewWebFile(url *url.URL) *WebFile { } } -// Read reads the File from it's web location. On the first -// call to Read, a GET request will be performed against the -// WebFile's URL, using Go's default HTTP client. Any further -// reads will keep reading from the HTTP Request body. -func (wf *WebFile) Read(b []byte) (int, error) { +func (wf *WebFile) start() error { if wf.body == nil { s := wf.url.String() resp, err := http.Get(s) if err != nil { - return 0, err + return err } if resp.StatusCode < 200 || resp.StatusCode > 299 { - return 0, fmt.Errorf("got non-2XX status code %d: %s", resp.StatusCode, s) + return fmt.Errorf("got non-2XX status code %d: %s", resp.StatusCode, s) } wf.body = resp.Body wf.contentLength = resp.ContentLength } + return nil +} + +// Read reads the File from it's web location. On the first +// call to Read, a GET request will be performed against the +// WebFile's URL, using Go's default HTTP client. Any further +// reads will keep reading from the HTTP Request body. +func (wf *WebFile) Read(b []byte) (int, error) { + if err := wf.start(); err != nil { + return 0, err + } return wf.body.Read(b) } @@ -60,6 +67,9 @@ func (wf *WebFile) Seek(offset int64, whence int) (int64, error) { } func (wf *WebFile) Size() (int64, error) { + if err := wf.start(); err != nil { + return 0, err + } if wf.contentLength < 0 { return -1, errors.New("Content-Length hearer was not set") } diff --git a/webfile_test.go b/webfile_test.go index 11eaa2d..450dffc 100644 --- a/webfile_test.go +++ b/webfile_test.go @@ -46,3 +46,52 @@ func TestWebFile_notFound(t *testing.T) { t.Fatal("expected error") } } + +func TestWebFileSize(t *testing.T) { + body := "Hello world!" + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, body) + })) + defer s.Close() + + u, err := url.Parse(s.URL) + if err != nil { + t.Fatal(err) + } + + // Read size before reading file. + + wf1 := NewWebFile(u) + if size, err := wf1.Size(); err != nil { + t.Error(err) + } else if int(size) != len(body) { + t.Errorf("expected size to be %d, got %d", len(body), size) + } + + actual, err := ioutil.ReadAll(wf1) + if err != nil { + t.Fatal(err) + } + if string(actual) != body { + t.Fatal("should have read the web file") + } + + wf1.Close() + + // Read size after reading file. + + wf2 := NewWebFile(u) + actual, err = ioutil.ReadAll(wf2) + if err != nil { + t.Fatal(err) + } + if string(actual) != body { + t.Fatal("should have read the web file") + } + + if size, err := wf2.Size(); err != nil { + t.Error(err) + } else if int(size) != len(body) { + t.Errorf("expected size to be %d, got %d", len(body), size) + } +}