package data import ( "bytes" "context" "encoding/json" "fmt" "io" "net/url" "os" "path/filepath" "strings" "github.com/spf13/afero" ) func readFile(_ context.Context, source *Source, args ...string) ([]byte, error) { if source.fs == nil { source.fs = afero.NewOsFs() } p := filepath.FromSlash(source.URL.Path) if len(args) == 1 { parsed, err := url.Parse(args[0]) if err != nil { return nil, err } if parsed.Path != "" { p = filepath.Join(p, parsed.Path) } // reset the media type - it may have been set by a parent dir read source.mediaType = "" } // make sure we can access the file i, err := source.fs.Stat(p) if err != nil { return nil, fmt.Errorf("stat %s: %w", p, err) } if strings.HasSuffix(p, string(filepath.Separator)) { source.mediaType = jsonArrayMimetype if i.IsDir() { return readFileDir(source, p) } return nil, fmt.Errorf("%s is not a directory", p) } f, err := source.fs.OpenFile(p, os.O_RDONLY, 0) if err != nil { return nil, fmt.Errorf("openFile %s: %w", p, err) } defer f.Close() b, err := io.ReadAll(f) if err != nil { return nil, fmt.Errorf("readAll %s: %w", p, err) } return b, nil } func readFileDir(source *Source, p string) ([]byte, error) { names, err := afero.ReadDir(source.fs, p) if err != nil { return nil, err } files := make([]string, len(names)) for i, v := range names { files[i] = v.Name() } var buf bytes.Buffer enc := json.NewEncoder(&buf) if err := enc.Encode(files); err != nil { return nil, err } b := buf.Bytes() // chop off the newline added by the json encoder return b[:len(b)-1], nil }