diff --git a/pkg/envoy/csv/decoder.go b/pkg/envoy/csv/decoder.go index bef566d74..dfa71b296 100644 --- a/pkg/envoy/csv/decoder.go +++ b/pkg/envoy/csv/decoder.go @@ -5,12 +5,11 @@ import ( "context" "encoding/csv" "io" - "os" - "path/filepath" "strings" "github.com/cortezaproject/corteza-server/pkg/envoy" "github.com/cortezaproject/corteza-server/pkg/envoy/resource" + "github.com/gabriel-vasile/mimetype" ) type ( @@ -31,8 +30,18 @@ func Decoder() *decoder { } // CanDecodeFile determines if the file can be determined by this decoder -func (y *decoder) CanDecodeFile(i os.FileInfo) bool { - return strings.Trim(filepath.Ext(i.Name()), ".") == "csv" +func (y *decoder) CanDecodeFile(f io.Reader) bool { + _, ext, err := mimetype.DetectReader(f) + if err != nil { + return false + } + + return y.CanDecodeExt(ext) +} + +func (y *decoder) CanDecodeExt(ext string) bool { + pt := strings.Split(ext, ".") + return strings.TrimSpace(pt[len(pt)-1]) == "csv" } // Decode decodes the given io.Reader into a generic resource dataset diff --git a/pkg/envoy/directory/decode.go b/pkg/envoy/directory/decode.go index a668c141a..d849334c1 100644 --- a/pkg/envoy/directory/decode.go +++ b/pkg/envoy/directory/decode.go @@ -14,7 +14,8 @@ import ( type ( decoder interface { - CanDecodeFile(os.FileInfo) bool + CanDecodeExt(string) bool + CanDecodeFile(io.Reader) bool Decode(context.Context, io.Reader, *envoy.DecoderOpts) ([]resource.Interface, error) } ) @@ -46,22 +47,30 @@ func Decode(ctx context.Context, p string, decoders ...decoder) ([]resource.Inte return nil } + if f, err = os.Open(p); err != nil { + return err + } + defer f.Close() + for _, d = range decoders { // find compatible decoder - if d.CanDecodeFile(info) { + if d.CanDecodeFile(f) { + break + } + // Do a fallback for extensions + if d.CanDecodeExt(info.Name()) { break } } - if d == nil { // no decoder found return nil } - if f, err = os.Open(p); err != nil { + _, err = f.Seek(0, 0) + if err != nil { return err } - defer f.Close() dir, fn := path.Split(p) do := &envoy.DecoderOpts{ diff --git a/pkg/envoy/json/decoder.go b/pkg/envoy/json/decoder.go index dfbd313ef..539e144f0 100644 --- a/pkg/envoy/json/decoder.go +++ b/pkg/envoy/json/decoder.go @@ -5,12 +5,12 @@ import ( "context" "encoding/json" "io" - "os" - "path/filepath" "strings" "github.com/cortezaproject/corteza-server/pkg/envoy" "github.com/cortezaproject/corteza-server/pkg/envoy/resource" + "github.com/cortezaproject/corteza-server/pkg/mime" + "github.com/gabriel-vasile/mimetype" ) type ( @@ -35,8 +35,30 @@ func Decoder() *decoder { } // CanDecodeFile determines if the file can be decoded by this decoder -func (d *decoder) CanDecodeFile(i os.FileInfo) bool { - return strings.Trim(filepath.Ext(i.Name()), ".") == "jsonl" +func (d *decoder) CanDecodeFile(f io.Reader) bool { + var buff bytes.Buffer + tr := io.TeeReader(f, &buff) + + _, ext, err := mimetype.DetectReader(tr) + if err != nil { + return false + } + + if ext == "txt" { + if is, err := mime.JsonL(&buff); err != nil { + return false + } else if is { + ext = "jsonl" + } + } + + return d.CanDecodeExt(ext) +} + +func (d *decoder) CanDecodeExt(ext string) bool { + pt := strings.Split(ext, ".") + ext = strings.TrimSpace(pt[len(pt)-1]) + return ext == "jsonl" || ext == "json" } // Decode decodes the given io.Reader into a generic resource dataset diff --git a/pkg/envoy/yaml/decoder.go b/pkg/envoy/yaml/decoder.go index d2b7e1265..f44d444a4 100644 --- a/pkg/envoy/yaml/decoder.go +++ b/pkg/envoy/yaml/decoder.go @@ -3,8 +3,6 @@ package yaml import ( "context" "io" - "os" - "path/filepath" "strings" "github.com/cortezaproject/corteza-server/pkg/envoy" @@ -29,16 +27,18 @@ func Decoder() *decoder { return &decoder{} } -// CanDecodeFile -func (y *decoder) CanDecodeFile(i os.FileInfo) bool { - switch strings.Trim(filepath.Ext(i.Name()), ".") { - case "yaml", "yml": - return true - } - +// CanDecodeFile checks if the file can be handled by this decoder +// +// @todo Add support for this; current library is unable to detect this. +func (y *decoder) CanDecodeFile(f io.Reader) bool { return false } +func (y *decoder) CanDecodeExt(ext string) bool { + pt := strings.Split(ext, ".") + return strings.TrimSpace(pt[len(pt)-1]) == "yaml" +} + func (y *decoder) Decode(ctx context.Context, r io.Reader, dctx *envoy.DecoderOpts) ([]resource.Interface, error) { var ( doc = &Document{} diff --git a/pkg/mime/mime.go b/pkg/mime/mime.go index 063c5adb3..96dca6fca 100644 --- a/pkg/mime/mime.go +++ b/pkg/mime/mime.go @@ -3,26 +3,13 @@ package mime import ( "bufio" "io" - - "github.com/gabriel-vasile/mimetype" ) -func Type(file io.ReadSeeker) (mt string, ext string, err error) { - if _, err = file.Seek(0, 0); err != nil { - return - } - - // Make sure we rewind when we're done - defer file.Seek(0, 0) - return mimetype.DetectReader(file) -} - -func JsonL(file io.ReadSeeker) (bool, error) { +func JsonL(f io.Reader) (bool, error) { // ExtractMimetype fails to detect json if jsonl is used // For now check if first rune is { - r := bufio.NewReader(file) + r := bufio.NewReader(f) rn, _, err := r.ReadRune() - defer file.Seek(0, 0) if err != nil { return false, err }