@@ -26,7 +26,7 @@ type ReqBuilderForm struct {
2626
2727templ ReqBuilderTab (txsSet vsl.TransactionSet ) {
2828 <div id =" tabRequest" class =" tabcontent" >
29- <p >Here you can generate a <a href =" https://curl.se/" target =" _blank" >curl</a > command based on parsed transactions VSL tags.</p >
29+ <p >Here you can generate commands with <a href =" https://curl.se/" target =" _blank" >curl</a > and other tools based on parsed VSL transaction tags. For POST/PUT requests, the < b >body is not available</ b > in varnishlog and won’t be included .</p >
3030 <form
3131 class =" simple-form"
3232 hx-post =" /reqbuilder/"
@@ -108,22 +108,22 @@ templ ReqBuilderTab(txsSet vsl.TransactionSet) {
108108
109109templ ReqBuild (txsSet vsl.TransactionSet , tx *vsl.Transaction , f ReqBuilderForm ) {
110110 <div class =" fade-me-in" >
111- <h3 >Command </h3 >
111+ <h3 >curl </h3 >
112112 <pre >
113113 <code >
114- @ templ.Raw (curlHeaders (tx, f))
114+ @ templ.Raw (curlCommand (tx, f))
115115 </code >
116116 </pre >
117- <h3 >{ tx. TXID () } </h3 >
117+ <h3 >python </h3 >
118118 <pre >
119119 <code >
120- @ templ.Raw (tx. FullRawLog ( false ))
120+ @ templ.Raw (pythonCommand (tx, f ))
121121 </code >
122122 </pre >
123123 </div >
124124}
125125
126- func curlHeaders (t *vsl .Transaction , f ReqBuilderForm ) string {
126+ func curlCommand (t *vsl .Transaction , f ReqBuilderForm ) string {
127127 var s strings.Builder
128128
129129 hdrState := header.NewHeaderState (t.LogRecords (), false )
@@ -153,6 +153,22 @@ func curlHeaders(t *vsl.Transaction, f ReqBuilderForm) string {
153153 }
154154 s.WriteString (fmt.Sprintf (` curl "%s://%s%s"` +" \\\n " , protocol, hostHdr.HeaderValue (), url.Value ()))
155155
156+ // Method
157+ method := t.FirstRecordOfType (vsl.MethodRecord {})
158+ if method == nil {
159+ return " Method not found!"
160+ }
161+
162+ switch method.Value () {
163+ case " GET" :
164+ // Nothing
165+ case " POST" , " PUT" :
166+ s.WriteString (" -X " + method.Value () + " \\\n " )
167+ s.WriteString (" -d '' \\\n " )
168+ default :
169+ s.WriteString (" -X " + method.Value () + " \\\n " )
170+ }
171+
156172 // Add headers
157173 var hdrVal string
158174 for _ , hc := range hdrState {
@@ -164,11 +180,12 @@ func curlHeaders(t *vsl.Transaction, f ReqBuilderForm) string {
164180 } else {
165181 hdrVal = hc.FinalValue ()
166182 }
183+ hdrVal = strings.ReplaceAll (hdrVal, ` "` , ` \"` )
167184 s.WriteString (fmt.Sprintf (` -H "%s: %s" \` +" \n " , hc.Header (), hdrVal))
168185 }
169186
170187 // Fixed options
171- s.WriteString (" -s -v -o /dev/null" )
188+ s.WriteString (" -s -k - v -o /dev/null" )
172189
173190 // Optional resolve
174191 switch f.ResolveTo {
@@ -192,6 +209,96 @@ func curlHeaders(t *vsl.Transaction, f ReqBuilderForm) string {
192209 return s.String ()
193210}
194211
212+ func pythonCommand (t *vsl .Transaction , f ReqBuilderForm ) string {
213+ var s strings.Builder
214+
215+ hdrState := header.NewHeaderState (t.LogRecords (), false )
216+
217+ // Find the host header
218+ hostHdr := hdrState.FindHeader (" host" , f.OriginalHeaders , true )
219+ if hostHdr == nil {
220+ return " Host header not found!"
221+ }
222+
223+ // Find the URL
224+ var url vsl.Record
225+ if f.OriginalURL {
226+ url = t.FirstRecordOfType (vsl.URLRecord {})
227+ } else {
228+ url = t.LastRecordOfType (vsl.URLRecord {})
229+ }
230+ if url == nil {
231+ return " URL not found!"
232+ }
233+
234+ // Set the protocol and port
235+ port := " 80"
236+ protocol := " http"
237+ if f.HTTPS {
238+ port = " 443"
239+ protocol = " https"
240+ }
241+
242+ s.WriteString (" import requests\n\n " )
243+
244+ includeHostHdr := false
245+
246+ // Optional resolve
247+ switch f.ResolveTo {
248+ case SendToLocalhost:
249+ s.WriteString (fmt.Sprintf (" url = \" %s ://%s%s \"\n\n " , protocol, " 127.0.0.1:" +port, url.Value ()))
250+ includeHostHdr = true
251+ case SendToBackend, SendToCustom:
252+ custom := strings.SplitN (f.CustomResolve , " :" , 2 )
253+ if custom[0 ] == " none" {
254+ return " Backed address not found for selected transaction."
255+ }
256+ if len (custom) < 2 {
257+ return " Incorrect backend address."
258+ }
259+ s.WriteString (fmt.Sprintf (" url = \" %s ://%s%s \"\n\n " , protocol, custom[0 ]+" :" +custom[1 ], url.Value ()))
260+ includeHostHdr = true
261+ }
262+
263+ // Add headers
264+ s.WriteString (" headers = {\n " )
265+ if includeHostHdr {
266+ s.WriteString (fmt.Sprintf (" \" %s \" : \" %s \" ,\n " , " Host" , hostHdr.HeaderValue ()))
267+ }
268+ for _ , hc := range hdrState {
269+ if hc.Header () == " host" || (f.OriginalHeaders && !hc.IsOriginalHeader ()) {
270+ continue
271+ }
272+ var hdrVal string
273+ if f.OriginalHeaders {
274+ hdrVal = hc.OriginalValue ()
275+ } else {
276+ hdrVal = hc.FinalValue ()
277+ }
278+ hdrVal = strings.ReplaceAll (hdrVal, ` "` , ` \"` )
279+ s.WriteString (fmt.Sprintf (" \" %s \" : \" %s \" ,\n " , hc.Header (), hdrVal))
280+ }
281+ s.WriteString (" }\n\n " )
282+
283+ // Method
284+ method := t.FirstRecordOfType (vsl.MethodRecord {})
285+ if method == nil {
286+ return " Method not found!"
287+ }
288+ switch method.Value () {
289+ case " GET" :
290+ s.WriteString (" response = requests.get(url, headers=headers, verify=False)\n " )
291+ case " POST" , " PUT" :
292+ s.WriteString (" response = requests." + strings.ToLower (method.Value ()) + " (url, headers=headers, verify=False, data={})\n " )
293+ default :
294+ s.WriteString (" response = requests." + strings.ToLower (method.Value ()) + " (url, headers=headers, verify=False)\n " )
295+ }
296+
297+ s.WriteString (" \n print(response.status_code)\n print(response.text)\n " )
298+
299+ return s.String ()
300+ }
301+
195302func getBackend (t *vsl .Transaction ) string {
196303 r := t.FirstRecordOfType (vsl.BackendOpenRecord {})
197304 if r == nil {
0 commit comments