1
1
package rpc
2
2
3
3
import (
4
+ "crypto/sha256"
4
5
"errors"
5
- "github.com/BigJk/snd/rpc/bind"
6
- "github.com/labstack/echo/v4"
7
- "github.com/vincent-petithory/dataurl"
6
+ "fmt"
7
+ "io"
8
8
"io/ioutil"
9
9
"net/http"
10
10
"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"
11
17
)
12
18
13
19
// RegisterImageUtilities registers all image utilities.
14
- func RegisterImageUtilities (route * echo.Group ) {
20
+ func RegisterImageUtilities (route * echo.Group , db database. Database ) {
15
21
// fetchImage fetches a image from a url and returns it as a dataurl.
16
22
bind .MustBind (route , "/fetchImage" , func (url string ) (string , error ) {
17
23
resp , err := http .Get (url )
@@ -30,4 +36,94 @@ func RegisterImageUtilities(route *echo.Group) {
30
36
31
37
return dataurl .EncodeBytes (data ), nil
32
38
})
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
+ })
33
129
}
0 commit comments