Skip to content

Commit d5fd60b

Browse files
committed
feat: implement hurl file build
1 parent 3401d9a commit d5fd60b

File tree

5 files changed

+68
-1
lines changed

5 files changed

+68
-1
lines changed

assets/templates/partials/reqbuild_partial.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
{{- range .Transactions.Set.Transactions }}
66
{{ if isTxTypeSession . }}{{ continue }}{{ end }}
77
<h3>{{ .TXID }}</h3>
8+
<h4>curl</h4>
89
<pre><code class="language-bash">{{- curlCommand . $data -}}</code></pre>
10+
<h4>hurl</h4>
11+
<pre><code class="language-http">{{- hurlFile . $data -}}</code></pre>
912
{{- end }}
1013
</div>
1114

assets/templates/views/reqbuild_view.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
<h1>Request Builder</h1>
66

77
<p>Generate <a href="https://curl.se/" target="_blank">curl</a>
8-
commands directly from parsed VSL transaction data. Note that for POST and PUT requests, the request body is not recorded by <code>varnishlog</code>
8+
commands or <a href="https://hurl.dev/" target="_blank">hurl</a>
9+
files directly from parsed VSL transaction data. Note that for POST and PUT requests, the request body is not recorded by <code>varnishlog</code>
910
and therefore cannot be included.</p>
1011

1112
<form class="reqbuild-form"

internal/server/html/helpers.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,11 @@ func curlCommand(tx *vsl.Transaction, cfg PageData) string {
7171
}
7272
return httpReq.CurlCommand(cfg.ReqBuild.Scheme, backend)
7373
}
74+
75+
func hurlFile(tx *vsl.Transaction, cfg PageData) string {
76+
httpReq, backend, err := processReqBuildForm(tx, cfg)
77+
if err != nil {
78+
return err.Error()
79+
}
80+
return httpReq.HurlFile(cfg.ReqBuild.Scheme, backend)
81+
}

internal/server/html/html.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ var funcMap = template.FuncMap{
5454
"renderTXLogTree": render.TxTreeHTML,
5555
"isTxTypeSession": func(tx *vsl.Transaction) bool { return tx.TXType == vsl.TxTypeSession },
5656
"curlCommand": curlCommand,
57+
"hurlFile": hurlFile,
5758
"timeline": render.Timeline,
5859
"sequence": render.Sequence,
5960
"timestampEventsSummary": summary.TimestampEventsSummary,

render/httpmodel.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,60 @@ func (r *HTTPRequest) CurlCommand(scheme string, backend *Backend) string {
174174
return s.String()
175175
}
176176

177+
// HurlFile generates a new hurl file as a string
178+
//
179+
// scheme can be "auto", "http://" or "https://"
180+
func (r *HTTPRequest) HurlFile(scheme string, backend *Backend) string {
181+
var s strings.Builder
182+
183+
// Parse scheme
184+
switch scheme {
185+
case "auto":
186+
if r.port == "443" {
187+
scheme = "https://"
188+
} else {
189+
// default to http for 80, empty, or any other port
190+
scheme = "http://"
191+
}
192+
case "http://", "https://":
193+
// keep as-is
194+
default:
195+
return "invalid scheme: " + scheme
196+
}
197+
198+
// Build host URL, append port only when provided
199+
hostURL := r.host
200+
if r.port != "" {
201+
hostURL = net.JoinHostPort(r.host, r.port)
202+
}
203+
204+
// Start hurl file
205+
s.WriteString(fmt.Sprintf("%s %s%s%s\n", r.method, scheme, hostURL, r.url))
206+
207+
// Headers
208+
for _, h := range r.headers {
209+
if h.name == vsl.HdrNameHost {
210+
continue
211+
}
212+
s.WriteString(fmt.Sprintf("%s: %s\n", h.name, h.value))
213+
}
214+
215+
// Options
216+
s.WriteString("\n[Options]\ninsecure: true\n")
217+
218+
// Connect-to
219+
// --connect-to HOST1:PORT1:HOST2:PORT2
220+
// when you would connect to HOST1:PORT1, actually connect to HOST2:PORT2
221+
if backend != nil {
222+
s.WriteString("\n# To connect to the backend run the hurl file as:\n")
223+
s.WriteString(fmt.Sprintf(`# hurl --connect-to "%s:%s:%s" file.hurl`,
224+
escapeDoubleQuotes(hostURL), escapeDoubleQuotes(backend.host), backend.port,
225+
))
226+
}
227+
228+
return s.String()
229+
}
230+
177231
// escapeDoubleQuotes is an utility function to escape double quotes ;)
178232
func escapeDoubleQuotes(s string) string {
179233
return strings.ReplaceAll(s, `"`, `\"`)

0 commit comments

Comments
 (0)