@@ -13,13 +13,75 @@ import (
13
13
14
14
log "github.com/codeshelldev/secured-signal-api/utils/logger"
15
15
query "github.com/codeshelldev/secured-signal-api/utils/query"
16
+ request "github.com/codeshelldev/secured-signal-api/utils/request"
16
17
)
17
18
18
19
type TemplateMiddleware struct {
19
20
Next http.Handler
20
21
Variables map [string ]interface {}
21
22
}
22
23
24
+ func (data TemplateMiddleware ) Use () http.Handler {
25
+ next := data .Next
26
+ VARIABLES := data .Variables
27
+
28
+ return http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
29
+ body , err := request .GetReqBody (w , req )
30
+
31
+ if err != nil {
32
+ log .Error ("Could not get Request Body: " , err .Error ())
33
+ }
34
+
35
+ bodyData := map [string ]interface {}{}
36
+
37
+ var modifiedBody bool
38
+
39
+ if ! body .Empty {
40
+ var modified bool
41
+
42
+ bodyData , modified = templateJSON (body .Data , VARIABLES )
43
+
44
+ if modified {
45
+ modifiedBody = true
46
+ }
47
+ }
48
+
49
+ if req .URL .RawQuery != "" {
50
+ var modified bool
51
+
52
+ req .URL .RawQuery , bodyData , modified = templateQuery (bodyData , req .URL , VARIABLES )
53
+
54
+ if modified {
55
+ modifiedBody = true
56
+ }
57
+ }
58
+
59
+ if modifiedBody {
60
+ modifiedBody , err := request .CreateBody (bodyData )
61
+
62
+ if err != nil {
63
+ http .Error (w , "Internal Error" , http .StatusInternalServerError )
64
+ return
65
+ }
66
+
67
+ body = modifiedBody
68
+
69
+ strData := body .ToString ()
70
+
71
+ log .Debug ("Applied Body Templating: " , strData )
72
+
73
+ req .ContentLength = int64 (len (strData ))
74
+ req .Header .Set ("Content-Length" , strconv .Itoa (len (strData )))
75
+ }
76
+
77
+ req .Body = io .NopCloser (bytes .NewReader (body .Raw ))
78
+
79
+ req .URL .Path , _ = templatePath (req .URL , VARIABLES )
80
+
81
+ next .ServeHTTP (w , req )
82
+ })
83
+ }
84
+
23
85
func renderTemplate (name string , tmplStr string , data any ) (string , error ) {
24
86
tmpl , err := template .New (name ).Parse (tmplStr )
25
87
@@ -36,15 +98,17 @@ func renderTemplate(name string, tmplStr string, data any) (string, error) {
36
98
return buf .String (), nil
37
99
}
38
100
39
- func templateJSON (data map [string ]interface {}, variables map [string ]interface {}) map [string ]interface {} {
101
+ func templateJSON (data map [string ]interface {}, variables map [string ]interface {}) (map [string ]interface {}, bool ) {
102
+ var modified bool
103
+
40
104
for k , v := range data {
41
105
str , ok := v .(string )
42
106
43
107
if ok {
44
108
re , err := regexp .Compile (`{{\s*\.([A-Za-z_][A-Za-z0-9_]*)\s*}}` )
45
109
46
110
if err != nil {
47
- log .Error ("Encountered Error while Compiling Regex: " , err .Error ())
111
+ log .Error ("Error while Compiling Regex: " , err .Error ())
48
112
}
49
113
50
114
matches := re .FindAllStringSubmatch (str , - 1 )
@@ -63,95 +127,77 @@ func templateJSON(data map[string]interface{}, variables map[string]interface{})
63
127
64
128
data [k ] = strings .ReplaceAll (str , string (variable ), tmplStr [0 ])
65
129
}
130
+
131
+ modified = true
66
132
} else if len (matches ) == 1 {
67
133
tmplKey := matches [0 ][1 ]
68
134
69
135
data [k ] = variables [tmplKey ]
136
+
137
+ modified = true
70
138
}
71
139
}
72
140
}
73
141
74
- return data
142
+ return data , modified
75
143
}
76
144
77
- func (data TemplateMiddleware ) Use () http.Handler {
78
- next := data .Next
79
- VARIABLES := data .Variables
80
-
81
- return http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
82
- bodyBytes , err := io .ReadAll (req .Body )
83
- if err != nil {
84
- log .Error ("Could not read Body: " , err .Error ())
85
- http .Error (w , "Bad Request" , http .StatusBadRequest )
86
- return
87
- }
88
- defer req .Body .Close ()
145
+ func templatePath (reqUrl * url.URL , VARIABLES interface {}) (string , bool ) {
146
+ var modified bool
89
147
90
- if len ( bodyBytes ) > 0 {
148
+ reqPath , err := url . PathUnescape ( reqUrl . Path )
91
149
92
- var modifiedBodyData map [string ]interface {}
93
-
94
- err = json .Unmarshal (bodyBytes , & modifiedBodyData )
95
-
96
- if err != nil {
97
- log .Error ("Could not decode Body: " , err .Error ())
98
- http .Error (w , "Internal Error" , http .StatusInternalServerError )
99
- return
100
- }
101
-
102
- modifiedBodyData = templateJSON (modifiedBodyData , VARIABLES )
103
-
104
- if req .URL .RawQuery != "" {
105
- decodedQuery , _ := url .QueryUnescape (req .URL .RawQuery )
150
+ if err != nil {
151
+ log .Error ("Error while Escaping Path: " , err .Error ())
152
+ return reqUrl .Path , modified
153
+ }
106
154
107
- log . Debug ( "Decoded Query: " , decodedQuery )
155
+ reqPath , err = renderTemplate ( "path" , reqPath , VARIABLES )
108
156
109
- templatedQuery , _ := renderTemplate ("query" , decodedQuery , VARIABLES )
157
+ if err != nil {
158
+ log .Error ("Could not Template Path: " , err .Error ())
159
+ return reqUrl .Path , modified
160
+ }
110
161
111
- modifiedQuery := req .URL .Query ()
162
+ if reqUrl .Path != reqPath {
163
+ log .Debug ("Applied Path Templating: " , reqPath )
112
164
113
- queryData := query .ParseRawQuery (templatedQuery )
165
+ modified = true
166
+ }
114
167
115
- for key , value := range queryData {
116
- keyWithoutPrefix , found := strings . CutPrefix ( key , "@" )
168
+ return reqPath , modified
169
+ }
117
170
118
- if found {
119
- modifiedBodyData [ keyWithoutPrefix ] = query . ParseTypedQuery ( value )
171
+ func templateQuery ( data map [ string ] interface {}, reqUrl * url. URL , VARIABLES interface {}) ( string , map [ string ] interface {}, bool ) {
172
+ var modified bool
120
173
121
- modifiedQuery .Del (key )
122
- }
123
- }
174
+ decodedQuery , _ := url .QueryUnescape (reqUrl .RawQuery )
124
175
125
- req . URL . RawQuery = modifiedQuery . Encode ( )
176
+ log . Debug ( "Decoded Query: " , decodedQuery )
126
177
127
- log .Debug ("Applied Query Templating: " , templatedQuery )
128
- }
178
+ templatedQuery , _ := renderTemplate ("query" , decodedQuery , VARIABLES )
129
179
130
- bodyBytes , err = json . Marshal ( modifiedBodyData )
180
+ modifiedQuery := reqUrl . Query ( )
131
181
132
- if err != nil {
133
- log .Error ("Could not encode Body: " , err .Error ())
134
- http .Error (w , "Internal Error" , http .StatusInternalServerError )
135
- return
136
- }
182
+ queryData := query .ParseRawQuery (templatedQuery )
137
183
138
- modifiedBody := string (bodyBytes )
184
+ for key , value := range queryData {
185
+ keyWithoutPrefix , found := strings .CutPrefix (key , "@" )
139
186
140
- log .Debug ("Applied Body Templating: " , modifiedBody )
187
+ if found {
188
+ data [keyWithoutPrefix ] = query .ParseTypedQuery (value )
141
189
142
- req .ContentLength = int64 (len (modifiedBody ))
143
- req .Header .Set ("Content-Length" , strconv .Itoa (len (modifiedBody )))
190
+ modifiedQuery .Del (key )
144
191
}
192
+ }
145
193
146
- req .Body = io .NopCloser (bytes .NewReader (bodyBytes ))
147
-
148
- reqPath := req .URL .Path
149
- reqPath , _ = url .PathUnescape (reqPath )
194
+ reqRawQuery := modifiedQuery .Encode ()
150
195
151
- modifiedReqPath , _ := renderTemplate ("path" , reqPath , VARIABLES )
196
+ if reqUrl .Query ().Encode () != reqRawQuery {
197
+ log .Debug ("Applied Query Templating: " , templatedQuery )
152
198
153
- req .URL .Path = modifiedReqPath
199
+ modified = true
200
+ }
154
201
155
- next .ServeHTTP (w , req )
156
- })
157
- }
202
+ return reqRawQuery , data , modified
203
+ }
0 commit comments