Skip to content

Commit be773da

Browse files
committed
feat(curl): add option to verbose http resp/req
1 parent 0f3a225 commit be773da

3 files changed

Lines changed: 36 additions & 0 deletions

File tree

docs/stackit_curl.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ stackit curl URL [flags]
2424
2525
Get all the DNS zones for project with ID xxx via GET request to https://dns.api.stackit.cloud/v1/projects/xxx/zones, with header "Authorization: Bearer yyy", fail if server returns error (such as 403 Forbidden)
2626
$ stackit curl https://dns.api.stackit.cloud/v1/projects/xxx/zones -X POST -H "Authorization: Bearer yyy" --fail
27+
28+
Get all the DNS zones via GET with request debugging enabled
29+
$ stackit curl https://dns.api.stackit.cloud/v1/projects/xxx/zones --verbose
2730
```
2831

2932
### Options
@@ -36,6 +39,7 @@ stackit curl URL [flags]
3639
--include If set, response headers are added to the output
3740
--output string Writes output to provided file instead of printing to console
3841
-X, --request string HTTP method, defaults to GET
42+
-v, --verbose Prints the full HTTP request and response for debugging
3943
```
4044

4145
### Options inherited from parent commands

internal/cmd/curl/curl.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const (
3131
includeResponseHeadersFlag = "include"
3232
failOnHTTPErrorFlag = "fail"
3333
outputFileFlag = "output"
34+
verboseFlag = "verbose"
3435
)
3536

3637
const (
@@ -45,6 +46,7 @@ type inputModel struct {
4546
IncludeResponseHeaders bool
4647
FailOnHTTPError bool
4748
OutputFile *string
49+
Verbose bool
4850
}
4951

5052
func NewCmd(params *types.CmdParams) *cobra.Command {
@@ -69,6 +71,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command {
6971
`Get all the DNS zones for project with ID xxx via GET request to https://dns.api.stackit.cloud/v1/projects/xxx/zones, with header "Authorization: Bearer yyy", fail if server returns error (such as 403 Forbidden)`,
7072
`$ stackit curl https://dns.api.stackit.cloud/v1/projects/xxx/zones -X POST -H "Authorization: Bearer yyy" --fail`,
7173
),
74+
examples.NewExample(
75+
"Get all the DNS zones via GET with request debugging enabled",
76+
"$ stackit curl https://dns.api.stackit.cloud/v1/projects/xxx/zones --verbose",
77+
),
7278
),
7379
Args: args.SingleArg(urlArg, utils.ValidateURLDomain),
7480
RunE: func(cmd *cobra.Command, args []string) (err error) {
@@ -87,13 +93,24 @@ func NewCmd(params *types.CmdParams) *cobra.Command {
8793
return err
8894
}
8995

96+
if model.Verbose {
97+
requestDump, _ := httputil.DumpRequest(req, true)
98+
params.Printer.Outputln(fmt.Sprintf("--- REQUEST ---\n%s", string(requestDump)))
99+
}
100+
90101
client := http.Client{
91102
Timeout: 30 * time.Second,
92103
}
93104
resp, err := client.Do(req)
94105
if err != nil {
95106
return fmt.Errorf("do request: %w", err)
96107
}
108+
109+
if model.Verbose {
110+
responseDump, _ := httputil.DumpResponse(resp, false)
111+
params.Printer.Outputln(fmt.Sprintf("--- RESPONSE ---\n%s", string(responseDump)))
112+
}
113+
97114
defer func() {
98115
closeErr := resp.Body.Close()
99116
if closeErr != nil {
@@ -136,6 +153,7 @@ func configureFlags(cmd *cobra.Command) {
136153
cmd.Flags().Bool(includeResponseHeadersFlag, false, "If set, response headers are added to the output")
137154
cmd.Flags().Bool(failOnHTTPErrorFlag, false, "If set, exits with error 22 if response code is 4XX or 5XX")
138155
cmd.Flags().String(outputFileFlag, "", "Writes output to provided file instead of printing to console")
156+
cmd.Flags().BoolP(verboseFlag, "v", false, "Prints the full HTTP request and response for debugging")
139157
}
140158

141159
func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) {
@@ -153,6 +171,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu
153171
IncludeResponseHeaders: flags.FlagToBoolValue(p, cmd, includeResponseHeadersFlag),
154172
FailOnHTTPError: flags.FlagToBoolValue(p, cmd, failOnHTTPErrorFlag),
155173
OutputFile: flags.FlagToStringPointer(p, cmd, outputFileFlag),
174+
Verbose: flags.FlagToBoolValue(p, cmd, verboseFlag),
156175
}
157176

158177
p.DebugInputModel(model)

internal/cmd/curl/curl_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st
4242
includeResponseHeadersFlag: "true",
4343
failOnHTTPErrorFlag: "true",
4444
outputFileFlag: "./output.txt",
45+
verboseFlag: "false",
4546
}
4647
for _, mod := range mods {
4748
mod(flagValues)
@@ -58,6 +59,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel {
5859
IncludeResponseHeaders: true,
5960
FailOnHTTPError: true,
6061
OutputFile: utils.Ptr("./output.txt"),
62+
Verbose: false,
6163
}
6264
for _, mod := range mods {
6365
mod(model)
@@ -213,6 +215,17 @@ func TestParseInput(t *testing.T) {
213215
)
214216
}),
215217
},
218+
{
219+
description: "verbose flag",
220+
argValues: fixtureArgValues(),
221+
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
222+
flagValues[verboseFlag] = "true"
223+
}),
224+
isValid: true,
225+
expectedModel: fixtureInputModel(func(model *inputModel) {
226+
model.Verbose = true
227+
}),
228+
},
216229
}
217230

218231
for _, tt := range tests {

0 commit comments

Comments
 (0)