11package rpc
22
33import (
4+ "crypto/sha256"
45 "errors"
5- "github.com/BigJk/snd/rpc/bind"
6- "github.com/labstack/echo/v4"
7- "github.com/vincent-petithory/dataurl"
6+ "fmt"
7+ "io"
88 "io/ioutil"
99 "net/http"
1010 "strings"
11+ "sync"
12+
13+ "github.com/BigJk/snd/database"
14+ "github.com/BigJk/snd/rpc/bind"
15+ "github.com/labstack/echo/v4"
16+ "github.com/vincent-petithory/dataurl"
1117)
1218
1319// RegisterImageUtilities registers all image utilities.
14- func RegisterImageUtilities (route * echo.Group ) {
20+ func RegisterImageUtilities (route * echo.Group , db database. Database ) {
1521 // fetchImage fetches a image from a url and returns it as a dataurl.
1622 bind .MustBind (route , "/fetchImage" , func (url string ) (string , error ) {
1723 resp , err := http .Get (url )
@@ -30,4 +36,94 @@ func RegisterImageUtilities(route *echo.Group) {
3036
3137 return dataurl .EncodeBytes (data ), nil
3238 })
39+
40+ //
41+ // Image cache to avoid using long data uris in the templates
42+ //
43+
44+ cacheMutex := sync.RWMutex {}
45+ cache := map [string ]string {}
46+
47+ decodeDataURI := func (dataURI string ) ([]byte , string , error ) {
48+ data , err := dataurl .DecodeString (dataURI )
49+ if err != nil {
50+ return nil , "" , err
51+ }
52+ contentType := http .DetectContentType (data .Data )
53+ return data .Data , contentType , nil
54+ }
55+
56+ // Fill cache with templates
57+ templates , err := db .GetTemplates ()
58+ if err == nil {
59+ for _ , template := range templates {
60+ for _ , img := range template .Images {
61+ hash := sha256 .Sum256 ([]byte (img ))
62+ hashHex := fmt .Sprintf ("%x" , hash )
63+
64+ cacheMutex .Lock ()
65+ cache [hashHex ] = img
66+ cacheMutex .Unlock ()
67+ }
68+ }
69+ }
70+
71+ route .POST ("/image-cache" , func (c echo.Context ) error {
72+ body , err := io .ReadAll (c .Request ().Body )
73+ if err != nil {
74+ return c .JSON (http .StatusBadRequest , err )
75+ }
76+
77+ dataUri := strings .Trim (string (body ), "\" " )
78+ hash := sha256 .Sum256 ([]byte (dataUri ))
79+ hashHex := fmt .Sprintf ("%x" , hash )
80+
81+ cacheMutex .Lock ()
82+ cache [hashHex ] = dataUri
83+ cacheMutex .Unlock ()
84+
85+ return c .NoContent (http .StatusOK )
86+ })
87+
88+ route .GET ("/image-cache/:id" , func (c echo.Context ) error {
89+ hash := c .Param ("id" )
90+
91+ cacheMutex .RLock ()
92+ val , ok := cache [hash ]
93+ cacheMutex .RUnlock ()
94+
95+ if ok {
96+ data , contentType , err := decodeDataURI (val )
97+ if err != nil {
98+ return c .JSON (http .StatusBadRequest , err )
99+ }
100+ return c .Blob (http .StatusOK , contentType , data )
101+ }
102+
103+ templates , err := db .GetTemplates ()
104+ if err != nil {
105+ return c .JSON (http .StatusBadRequest , err )
106+ }
107+
108+ for _ , template := range templates {
109+ for _ , img := range template .Images {
110+ hash := sha256 .Sum256 ([]byte (img ))
111+ hashHex := fmt .Sprintf ("%x" , hash )
112+
113+ cacheMutex .Lock ()
114+ cache [hashHex ] = img
115+ cacheMutex .Unlock ()
116+
117+ if hashHex == c .Param ("id" ) {
118+ data , contentType , err := decodeDataURI (img )
119+ if err != nil {
120+ return c .JSON (http .StatusBadRequest , err )
121+ }
122+ return c .Blob (http .StatusOK , contentType , data )
123+ }
124+ }
125+ }
126+
127+ return c .JSON (http .StatusBadRequest , errors .New ("image not found" ))
128+ })
33129}
0 commit comments