Skip to content

Commit a9301d5

Browse files
authored
Merge pull request #262 from twitchdev/feature-261
Feature Request 261
2 parents 09fd51c + 37252ba commit a9301d5

File tree

5 files changed

+77
-8
lines changed

5 files changed

+77
-8
lines changed

cmd/api.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ var body string
2121
var prettyPrint bool
2222
var autoPaginate int = 0
2323
var port int
24+
var verbose bool
2425

2526
var generateCount int
2627

@@ -89,6 +90,7 @@ func init() {
8990

9091
apiCmd.PersistentFlags().StringArrayVarP(&queryParameters, "query-params", "q", nil, "Available multiple times. Passes in query parameters to endpoints using the format of `key=value`.")
9192
apiCmd.PersistentFlags().StringVarP(&body, "body", "b", "", "Passes a body to the request. Alteratively supports CURL-like references to files using the format of `@data,json`.")
93+
apiCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Whether to display HTTP request and header information above the response of the API call.")
9294

9395
// default here is false to enable -p commands to toggle off without explicitly defining -p=false as -p false will not work. The below commands invert the bool to pass the true default. Deprecated, so marking as hidden in favor of the unformatted flag.
9496
apiCmd.PersistentFlags().BoolVarP(&prettyPrint, "pretty-print", "p", false, "Whether to pretty-print API requests. Default is true.")
@@ -127,9 +129,9 @@ func cmdRun(cmd *cobra.Command, args []string) error {
127129
}
128130

129131
if cmd.Name() == "get" && cmd.PersistentFlags().Lookup("autopaginate").Changed {
130-
return api.NewRequest(cmd.Name(), path, queryParameters, []byte(body), !prettyPrint, &autoPaginate)
132+
return api.NewRequest(cmd.Name(), path, queryParameters, []byte(body), !prettyPrint, &autoPaginate, verbose)
131133
} else {
132-
return api.NewRequest(cmd.Name(), path, queryParameters, []byte(body), !prettyPrint, nil) // only set on when the user changed the flag
134+
return api.NewRequest(cmd.Name(), path, queryParameters, []byte(body), !prettyPrint, nil, verbose) // only set on when the user changed the flag
133135
}
134136
}
135137

docs/api.md

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Allows the user to make GET calls to endpoints on Helix. Requires a logged in to
3737
| `--query-param` | `-q` | Query parameters for the endpoint in `key=value` format. Multiple can be entered to give multiple parameters. | `get -q login=ninja` | N |
3838
| `--unformatted` | `-u` | Whether to return unformatted responses. Default is `false`. | `get -u` | N |
3939
| `--autopaginate` | `-P` | Whether to autopaginate the response from Twitch, and optionally the number of pages to limit. **WARNING** This flag can cause extremely large payloads and cause issues with some terminals. Default is to not autopaginate, however if provided, the default is gets all responses. | `get -P=10` | N |
40+
| `--verbose` | `-v` | Whether to display HTTP request and header information above the response of the API call. | `get -v` | N |
4041

4142
**Examples**
4243

internal/api/api.go

+54-1
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,18 @@ type clientInformation struct {
3030
}
3131

3232
// NewRequest is used to request data from the Twitch API using a HTTP GET request- this function is a wrapper for the apiRequest function that handles the network call
33-
func NewRequest(method string, path string, queryParameters []string, body []byte, prettyPrint bool, autopaginate *int) error {
33+
func NewRequest(method string, path string, queryParameters []string, body []byte, prettyPrint bool, autopaginate *int, verbose bool) error {
3434
var data models.APIResponse
3535
var err error
3636
var cursor string
3737

38+
var requestMethod string
39+
var requestPath string
40+
var requestHeaders http.Header
41+
var responseHeaders http.Header
42+
var responseStatusCode int
43+
var protocol string
44+
3845
isExtensionsLiveEndpoint := false // https://github.com/twitchdev/twitch-cli/issues/157
3946

4047
data.Data = make([]interface{}, 0)
@@ -130,6 +137,13 @@ func NewRequest(method string, path string, queryParameters []string, body []byt
130137

131138
if runCounter == 1 {
132139
data = apiResponse
140+
141+
requestMethod = resp.HttpMethod
142+
requestPath = resp.RequestPath
143+
responseStatusCode = resp.StatusCode
144+
requestHeaders = resp.RequestHeaders
145+
responseHeaders = resp.ResponseHeaders
146+
protocol = resp.HttpVersion
133147
}
134148

135149
if resp.StatusCode > 299 || resp.StatusCode < 200 {
@@ -210,6 +224,10 @@ func NewRequest(method string, path string, queryParameters []string, body []byt
210224
// since Command Prompt/Powershell don't support coloring, will pretty print without colors
211225
if runtime.GOOS == "windows" {
212226
s, _ := json.MarshalIndent(obj, "", " ")
227+
228+
if verbose {
229+
printVerboseHeaders(requestMethod, requestPath, requestHeaders, responseHeaders, responseStatusCode, protocol)
230+
}
213231
if data.Error == "" {
214232
fmt.Println(string(s))
215233
} else {
@@ -226,6 +244,10 @@ func NewRequest(method string, path string, queryParameters []string, body []byt
226244
if err != nil {
227245
return err
228246
}
247+
248+
if verbose {
249+
printVerboseHeaders(requestMethod, requestPath, requestHeaders, responseHeaders, responseStatusCode, protocol)
250+
}
229251
if data.Error == "" {
230252
fmt.Println(string(s))
231253
} else {
@@ -234,6 +256,9 @@ func NewRequest(method string, path string, queryParameters []string, body []byt
234256
return nil
235257
}
236258

259+
if verbose {
260+
printVerboseHeaders(requestMethod, requestPath, requestHeaders, responseHeaders, responseStatusCode, protocol)
261+
}
237262
if data.Error == "" {
238263
fmt.Println(string(d))
239264
} else {
@@ -297,3 +322,31 @@ func GetClientInformation() (clientInformation, error) {
297322

298323
return clientInformation{Token: token, ClientID: clientID}, nil
299324
}
325+
326+
func printVerboseHeaders(method string, path string, requestHeaders http.Header, responseHeaders http.Header, responseStatusCode int, protocol string) {
327+
fmt.Printf("* Using %v\n", protocol)
328+
fmt.Printf("> %v %v\n", method, path)
329+
for key, value := range requestHeaders {
330+
for _, v := range value {
331+
if strings.EqualFold(key, "authorization") {
332+
parts := strings.Split(v, " ")
333+
if len(parts) > 1 {
334+
fmt.Printf("> %v: %v *****\n", key, parts[0])
335+
} else {
336+
fmt.Printf("> %v: *****\n", key)
337+
}
338+
} else {
339+
fmt.Printf("> %v: %v\n", key, v)
340+
}
341+
}
342+
}
343+
344+
fmt.Printf("\n")
345+
fmt.Printf("< %v %v %v\n", protocol, responseStatusCode, http.StatusText(responseStatusCode))
346+
for key, value := range responseHeaders {
347+
for _, v := range value {
348+
fmt.Printf("< %v: %v\n", key, v)
349+
}
350+
}
351+
fmt.Printf("\n")
352+
}

internal/api/api_request.go

+13
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"bytes"
77
"fmt"
88
"io/ioutil"
9+
"net/http"
910
"time"
1011

1112
"github.com/twitchdev/twitch-cli/internal/request"
@@ -19,6 +20,12 @@ type apiRequestParameters struct {
1920
type apiRequestResponse struct {
2021
StatusCode int
2122
Body []byte
23+
24+
HttpMethod string
25+
RequestPath string
26+
RequestHeaders http.Header
27+
ResponseHeaders http.Header
28+
HttpVersion string
2229
}
2330

2431
func apiRequest(method string, url string, payload []byte, p apiRequestParameters) (apiRequestResponse, error) {
@@ -54,5 +61,11 @@ func apiRequest(method string, url string, payload []byte, p apiRequestParameter
5461
return apiRequestResponse{
5562
StatusCode: resp.StatusCode,
5663
Body: body,
64+
65+
HttpMethod: req.Method,
66+
RequestPath: req.URL.RequestURI(),
67+
RequestHeaders: req.Header,
68+
ResponseHeaders: resp.Header,
69+
HttpVersion: req.Proto,
5770
}, nil
5871
}

internal/api/api_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,17 @@ func TestNewRequest(t *testing.T) {
5656

5757
defaultAutoPaginate := 0
5858
// tests for normal get requests
59-
NewRequest("GET", "", []string{"test=1", "test=2"}, nil, true, nil)
60-
NewRequest("GET", "", []string{"test=1", "test=2"}, nil, false, &defaultAutoPaginate)
59+
NewRequest("GET", "", []string{"test=1", "test=2"}, nil, true, nil, false)
60+
NewRequest("GET", "", []string{"test=1", "test=2"}, nil, false, &defaultAutoPaginate, false)
6161

6262
// testing cursors autopagination
63-
NewRequest("GET", "/cursor", []string{"test=1", "test=2"}, nil, false, &defaultAutoPaginate)
63+
NewRequest("GET", "/cursor", []string{"test=1", "test=2"}, nil, false, &defaultAutoPaginate, false)
6464

6565
// testing 204 no-content apis
66-
NewRequest("POST", "/nocontent", []string{"test=1", "test=2"}, nil, false, nil)
66+
NewRequest("POST", "/nocontent", []string{"test=1", "test=2"}, nil, false, nil, false)
6767

6868
// testing 500 errors
69-
NewRequest("GET", "/error", []string{"test=1", "test=2"}, nil, false, &defaultAutoPaginate)
69+
NewRequest("GET", "/error", []string{"test=1", "test=2"}, nil, false, &defaultAutoPaginate, false)
7070
}
7171

7272
func TestValidOptions(t *testing.T) {

0 commit comments

Comments
 (0)