Skip to content

Commit d6945f0

Browse files
committed
impr: backward-compatible compliance with rfc 2397
1 parent 460493e commit d6945f0

2 files changed

Lines changed: 55 additions & 16 deletions

File tree

internal/fileio/fileio.go

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,24 +72,31 @@ func ReadJson[T any](path string) (T, error) {
7272

7373
// WriteFile writes the file to disk.
7474
// The content can be text or binary (encoded as a data URL),
75-
// e.g. data:;base64,MTIz
75+
// e.g. data:application/octet-stream;base64,MTIz
7676
func WriteFile(path, content string, perm fs.FileMode) (err error) {
7777
var data []byte
78-
// TODO: only check for "data:;base64," to comply with RFC 2397.
79-
// Remove the "data:" check after the snippet reaches 0.16.
80-
if strings.HasPrefix(content, "data:") || strings.HasPrefix(content, "data:;base64,") {
81-
// data-url encoded file
82-
_, encoded, found := strings.Cut(content, ",")
83-
if !found {
84-
return errors.New("invalid data-url encoding")
85-
}
86-
data, err = base64.StdEncoding.DecodeString(encoded)
87-
if err != nil {
88-
return err
89-
}
90-
} else {
78+
if !strings.HasPrefix(content, "data:") {
9179
// text file
9280
data = []byte(content)
81+
return os.WriteFile(path, data, perm)
82+
}
83+
84+
// data-url encoded file
85+
meta, encoded, found := strings.Cut(content, ",")
86+
if !found {
87+
return errors.New("invalid data-url encoding")
88+
}
89+
90+
if !strings.HasSuffix(meta, "base64") {
91+
// no need to decode
92+
data = []byte(encoded)
93+
return os.WriteFile(path, data, perm)
94+
}
95+
96+
// decode base64-encoded data
97+
data, err = base64.StdEncoding.DecodeString(encoded)
98+
if err != nil {
99+
return err
93100
}
94101
return os.WriteFile(path, data, perm)
95102
}

internal/fileio/fileio_test.go

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,24 @@ func TestWriteFile(t *testing.T) {
173173
}
174174
})
175175

176-
t.Run("binary", func(t *testing.T) {
177-
path := filepath.Join(dir, "data.bin")
176+
t.Run("data-octet-stream", func(t *testing.T) {
177+
path := filepath.Join(dir, "data-1.bin")
178+
err = WriteFile(path, "data:application/octet-stream;base64,MTIz", 0444)
179+
if err != nil {
180+
t.Fatalf("expected nil err, got %v", err)
181+
}
182+
got, err := os.ReadFile(path)
183+
if err != nil {
184+
t.Fatalf("read file: expected nil err, got %v", err)
185+
}
186+
want := []byte("123")
187+
if !reflect.DeepEqual(got, want) {
188+
t.Errorf("read file: expected %v, got %v", want, got)
189+
}
190+
})
191+
192+
t.Run("data-base64", func(t *testing.T) {
193+
path := filepath.Join(dir, "data-2.bin")
178194
err = WriteFile(path, "data:;base64,MTIz", 0444)
179195
if err != nil {
180196
t.Fatalf("expected nil err, got %v", err)
@@ -189,6 +205,22 @@ func TestWriteFile(t *testing.T) {
189205
}
190206
})
191207

208+
t.Run("data-text-plain", func(t *testing.T) {
209+
path := filepath.Join(dir, "data-3.bin")
210+
err = WriteFile(path, "data:text/plain;,123", 0444)
211+
if err != nil {
212+
t.Fatalf("expected nil err, got %v", err)
213+
}
214+
got, err := os.ReadFile(path)
215+
if err != nil {
216+
t.Fatalf("read file: expected nil err, got %v", err)
217+
}
218+
want := []byte("123")
219+
if !reflect.DeepEqual(got, want) {
220+
t.Errorf("read file: expected %v, got %v", want, got)
221+
}
222+
})
223+
192224
t.Run("perm", func(t *testing.T) {
193225
const perm = 0444
194226
path := filepath.Join(dir, "perm.txt")

0 commit comments

Comments
 (0)