Skip to content

Commit a7c9ea1

Browse files
Merge pull request #34 from frictionlessdata/fiz_load_zip_datapackage
Fix loading remote zip datapackages
2 parents f9714f5 + ae7db7d commit a7c9ea1

File tree

4 files changed

+52
-31
lines changed

4 files changed

+52
-31
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@
1313
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
1414
.glide/
1515

16-
covprofile
16+
covprofile
17+
18+
.DS_Store

datapackage/package.go

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ func (p *Package) Zip(path string) error {
181181
fPaths := []string{descriptorPath}
182182
for _, r := range p.resources {
183183
for _, p := range r.path {
184-
c, err := read(filepath.Join(r.basePath, p))
184+
_, c, err := read(filepath.Join(r.basePath, p))
185185
if err != nil {
186186
return err
187187
}
@@ -293,7 +293,7 @@ func FromString(in string, basePath string, loaders ...validator.RegistryLoader)
293293
// Load the data package descriptor from the specified URL or file path.
294294
// If path has the ".zip" extension, it will be saved in local filesystem and decompressed before loading.
295295
func Load(path string, loaders ...validator.RegistryLoader) (*Package, error) {
296-
contents, err := read(path)
296+
localPath, contents, err := read(path)
297297
if err != nil {
298298
return nil, fmt.Errorf("error reading path contents (%s): %w", path, err)
299299
}
@@ -305,34 +305,47 @@ func Load(path string, loaders ...validator.RegistryLoader) (*Package, error) {
305305
if err != nil {
306306
return nil, fmt.Errorf("error creating temporary directory: %w", err)
307307
}
308-
fNames, err := unzip(path, dir)
308+
fNames, err := unzip(localPath, dir)
309309
if err != nil {
310-
return nil, fmt.Errorf("error unzipping path contents (%s): %w", path, err)
310+
return nil, fmt.Errorf("error unzipping path contents (%s): %w", localPath, err)
311311
}
312312
if _, ok := fNames[descriptorFileNameWithinZip]; ok {
313313
return Load(filepath.Join(dir, descriptorFileNameWithinZip), loaders...)
314314
}
315-
return nil, fmt.Errorf("zip file %s does not contain a file called %s", path, descriptorFileNameWithinZip)
315+
return nil, fmt.Errorf("zip file %s does not contain a file called %s", localPath, descriptorFileNameWithinZip)
316316
}
317317

318-
func read(path string) ([]byte, error) {
318+
func read(path string) (string, []byte, error) {
319319
if strings.HasPrefix(path, "http") {
320320
resp, err := http.Get(path)
321321
if err != nil {
322-
return nil, fmt.Errorf("error performing HTTP GET(%s): %w", path, err)
322+
return "", nil, fmt.Errorf("error performing HTTP GET(%s): %w", path, err)
323323
}
324324
defer resp.Body.Close()
325325
buf, err := ioutil.ReadAll(resp.Body)
326326
if err != nil {
327-
return nil, fmt.Errorf("error reading response body contents (%s): %w", path, err)
327+
return "", nil, fmt.Errorf("error reading response body contents (%s): %w", path, err)
328328
}
329-
return buf, nil
329+
// Making sure zip file is materialized.
330+
// This makes debugging easier.
331+
localPath, err := func() (string, error) {
332+
f, err := ioutil.TempFile("", "*.zip")
333+
if err != nil {
334+
return "", fmt.Errorf("error creating temp file to save zip (dir:%s): %w", os.TempDir(), err)
335+
}
336+
defer f.Close()
337+
if _, err := f.Write(buf); err != nil {
338+
return f.Name(), fmt.Errorf("error writing temp file to save zip (%s): %w", f.Name(), err)
339+
}
340+
return f.Name(), nil
341+
}()
342+
return localPath, buf, err
330343
}
331344
buf, err := ioutil.ReadFile(path)
332345
if err != nil {
333-
return nil, fmt.Errorf("error reading local file contents (%s): %w", path, err)
346+
return "", nil, fmt.Errorf("error reading local file contents (%s): %w", path, err)
334347
}
335-
return buf, nil
348+
return path, buf, nil
336349
}
337350

338351
func unzip(archive, basePath string) (map[string]struct{}, error) {

datapackage/package_test.go

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"os"
1313
"path/filepath"
1414
"reflect"
15+
"strconv"
1516
"strings"
1617
"testing"
1718

@@ -456,26 +457,11 @@ func TestLoad(t *testing.T) {
456457
})
457458
t.Run("LocalZip", func(t *testing.T) {
458459
is := is.New(t)
459-
// Creating a zip file.
460-
fName := filepath.Join(dir, "pkg.zip")
461-
zipFile, err := os.Create(fName)
460+
pkg, err := Load("test_package.zip", validator.InMemoryLoader())
462461
is.NoErr(err)
463-
defer zipFile.Close()
464-
465-
// Adding a datapackage.json file to the zip with proper contents.
466-
w := zip.NewWriter(zipFile)
467-
f, err := w.Create("datapackage.json")
468-
is.NoErr(err)
469-
_, err = f.Write([]byte(r1Str))
470-
is.NoErr(err)
471-
is.NoErr(w.Close())
472-
473-
// Load and check package.
474-
pkg, err := Load(fName, validator.InMemoryLoader())
475-
is.NoErr(err)
476-
res := pkg.GetResource("res1")
477-
is.Equal(res.name, "res1")
478-
is.Equal(res.path, []string{"foo.csv"})
462+
res := pkg.GetResource("books")
463+
is.Equal(res.name, "books")
464+
is.Equal(res.path, []string{"data.csv"})
479465
})
480466
t.Run("LocalZipWithSubdirs", func(t *testing.T) {
481467
is := is.New(t)
@@ -549,6 +535,26 @@ func TestLoad(t *testing.T) {
549535
})
550536
}
551537
})
538+
t.Run("RemoteZip", func(t *testing.T) {
539+
is := is.New(t)
540+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
541+
f, err := os.Open("test_package.zip")
542+
is.NoErr(err)
543+
defer f.Close()
544+
545+
stat, err := f.Stat()
546+
is.NoErr(err)
547+
w.Header().Set("Content-Type", "application/octet-stream")
548+
w.Header().Set("Content-Length", strconv.FormatInt(stat.Size(), 10)) //Get file size as a string
549+
io.Copy(w, f)
550+
}))
551+
defer ts.Close()
552+
pkg, err := Load(ts.URL+"/package.zip", validator.InMemoryLoader())
553+
is.NoErr(err)
554+
res := pkg.GetResource("books")
555+
is.Equal(res.name, "books")
556+
is.Equal(res.path, []string{"data.csv"})
557+
})
552558
t.Run("InvalidPath", func(t *testing.T) {
553559
_, err := Load("foobar", validator.InMemoryLoader())
554560
if err == nil {

datapackage/test_package.zip

657 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)