@@ -13,13 +13,75 @@ import (
1313
1414 log "github.com/codeshelldev/secured-signal-api/utils/logger"
1515 query "github.com/codeshelldev/secured-signal-api/utils/query"
16+ request "github.com/codeshelldev/secured-signal-api/utils/request"
1617)
1718
1819type TemplateMiddleware struct {
1920 Next http.Handler
2021 Variables map [string ]interface {}
2122}
2223
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+
2385func renderTemplate (name string , tmplStr string , data any ) (string , error ) {
2486 tmpl , err := template .New (name ).Parse (tmplStr )
2587
@@ -36,15 +98,17 @@ func renderTemplate(name string, tmplStr string, data any) (string, error) {
3698 return buf .String (), nil
3799}
38100
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+
40104 for k , v := range data {
41105 str , ok := v .(string )
42106
43107 if ok {
44108 re , err := regexp .Compile (`{{\s*\.([A-Za-z_][A-Za-z0-9_]*)\s*}}` )
45109
46110 if err != nil {
47- log .Error ("Encountered Error while Compiling Regex: " , err .Error ())
111+ log .Error ("Error while Compiling Regex: " , err .Error ())
48112 }
49113
50114 matches := re .FindAllStringSubmatch (str , - 1 )
@@ -63,95 +127,77 @@ func templateJSON(data map[string]interface{}, variables map[string]interface{})
63127
64128 data [k ] = strings .ReplaceAll (str , string (variable ), tmplStr [0 ])
65129 }
130+
131+ modified = true
66132 } else if len (matches ) == 1 {
67133 tmplKey := matches [0 ][1 ]
68134
69135 data [k ] = variables [tmplKey ]
136+
137+ modified = true
70138 }
71139 }
72140 }
73141
74- return data
142+ return data , modified
75143}
76144
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
89147
90- if len ( bodyBytes ) > 0 {
148+ reqPath , err := url . PathUnescape ( reqUrl . Path )
91149
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+ }
106154
107- log . Debug ( "Decoded Query: " , decodedQuery )
155+ reqPath , err = renderTemplate ( "path" , reqPath , VARIABLES )
108156
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+ }
110161
111- modifiedQuery := req .URL .Query ()
162+ if reqUrl .Path != reqPath {
163+ log .Debug ("Applied Path Templating: " , reqPath )
112164
113- queryData := query .ParseRawQuery (templatedQuery )
165+ modified = true
166+ }
114167
115- for key , value := range queryData {
116- keyWithoutPrefix , found := strings . CutPrefix ( key , "@" )
168+ return reqPath , modified
169+ }
117170
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
120173
121- modifiedQuery .Del (key )
122- }
123- }
174+ decodedQuery , _ := url .QueryUnescape (reqUrl .RawQuery )
124175
125- req . URL . RawQuery = modifiedQuery . Encode ( )
176+ log . Debug ( "Decoded Query: " , decodedQuery )
126177
127- log .Debug ("Applied Query Templating: " , templatedQuery )
128- }
178+ templatedQuery , _ := renderTemplate ("query" , decodedQuery , VARIABLES )
129179
130- bodyBytes , err = json . Marshal ( modifiedBodyData )
180+ modifiedQuery := reqUrl . Query ( )
131181
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 )
137183
138- modifiedBody := string (bodyBytes )
184+ for key , value := range queryData {
185+ keyWithoutPrefix , found := strings .CutPrefix (key , "@" )
139186
140- log .Debug ("Applied Body Templating: " , modifiedBody )
187+ if found {
188+ data [keyWithoutPrefix ] = query .ParseTypedQuery (value )
141189
142- req .ContentLength = int64 (len (modifiedBody ))
143- req .Header .Set ("Content-Length" , strconv .Itoa (len (modifiedBody )))
190+ modifiedQuery .Del (key )
144191 }
192+ }
145193
146- req .Body = io .NopCloser (bytes .NewReader (bodyBytes ))
147-
148- reqPath := req .URL .Path
149- reqPath , _ = url .PathUnescape (reqPath )
194+ reqRawQuery := modifiedQuery .Encode ()
150195
151- modifiedReqPath , _ := renderTemplate ("path" , reqPath , VARIABLES )
196+ if reqUrl .Query ().Encode () != reqRawQuery {
197+ log .Debug ("Applied Query Templating: " , templatedQuery )
152198
153- req .URL .Path = modifiedReqPath
199+ modified = true
200+ }
154201
155- next .ServeHTTP (w , req )
156- })
157- }
202+ return reqRawQuery , data , modified
203+ }
0 commit comments