github.com/puellanivis/breton@v0.2.16/lib/files/datafiles/data.go (about) 1 // Package datafiles implements the "data:" URL scheme. 2 package datafiles 3 4 import ( 5 "context" 6 "encoding/base64" 7 "net/http" 8 "net/url" 9 "os" 10 "strings" 11 "time" 12 13 "github.com/puellanivis/breton/lib/files" 14 "github.com/puellanivis/breton/lib/files/wrapper" 15 ) 16 17 type handler struct{} 18 19 func init() { 20 files.RegisterScheme(&handler{}, "data") 21 } 22 23 var b64enc = base64.StdEncoding 24 25 func (h *handler) Create(ctx context.Context, uri *url.URL) (files.Writer, error) { 26 return nil, files.PathError("create", uri.String(), os.ErrInvalid) 27 } 28 29 type withHeaders struct { 30 files.Reader 31 header http.Header 32 } 33 34 func (w *withHeaders) Header() http.Header { 35 return w.header 36 } 37 38 func (h *handler) Open(ctx context.Context, uri *url.URL) (files.Reader, error) { 39 if uri.Host != "" || uri.User != nil { 40 return nil, files.PathError("open", uri.String(), os.ErrInvalid) 41 } 42 43 path := uri.Path 44 if path == "" { 45 path = uri.Opaque 46 if p, err := url.PathUnescape(path); err == nil { 47 path = p 48 } 49 } 50 51 i := strings.IndexByte(path, ',') 52 if i < 0 { 53 return nil, files.PathError("open", uri.String(), os.ErrInvalid) 54 } 55 56 contentType, data := path[:i], []byte(path[i+1:]) 57 var isBase64 bool 58 59 if strings.HasSuffix(contentType, ";base64") { 60 contentType = strings.TrimSuffix(contentType, ";base64") 61 isBase64 = true 62 } 63 64 if contentType == "" { 65 contentType = "text/plain;charset=US-ASCII" 66 } 67 68 header := make(http.Header) 69 header.Set("Content-Type", contentType) 70 71 if isBase64 { 72 b := make([]byte, b64enc.DecodedLen(len(data))) 73 74 n, err := b64enc.Decode(b, data) 75 if err != nil { 76 return nil, files.PathError("decode", uri.String(), err) 77 } 78 79 data = b[:n] 80 } 81 82 return &withHeaders{ 83 Reader: wrapper.NewReaderFromBytes(data, uri, time.Now()), 84 header: header, 85 }, nil 86 } 87 88 func (h *handler) List(ctx context.Context, uri *url.URL) ([]os.FileInfo, error) { 89 return nil, files.PathError("readdir", uri.String(), os.ErrInvalid) 90 }