Skip to content

Commit

Permalink
Adds header information to 'twitch api'. Addresses 261
Browse files Browse the repository at this point in the history
  • Loading branch information
Xemdo committed Aug 13, 2023
1 parent 2f6df3b commit 2404139
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 8 deletions.
6 changes: 4 additions & 2 deletions cmd/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var body string
var prettyPrint bool
var autoPaginate int = 0
var port int
var verbose bool

var generateCount int

Expand Down Expand Up @@ -89,6 +90,7 @@ func init() {

apiCmd.PersistentFlags().StringArrayVarP(&queryParameters, "query-params", "q", nil, "Available multiple times. Passes in query parameters to endpoints using the format of `key=value`.")
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`.")
apiCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Whether to display HTTP request and header information above the response of the API call.")

// 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.
apiCmd.PersistentFlags().BoolVarP(&prettyPrint, "pretty-print", "p", false, "Whether to pretty-print API requests. Default is true.")
Expand Down Expand Up @@ -127,9 +129,9 @@ func cmdRun(cmd *cobra.Command, args []string) error {
}

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

Expand Down
55 changes: 54 additions & 1 deletion internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,18 @@ type clientInformation struct {
}

// 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
func NewRequest(method string, path string, queryParameters []string, body []byte, prettyPrint bool, autopaginate *int) error {
func NewRequest(method string, path string, queryParameters []string, body []byte, prettyPrint bool, autopaginate *int, verbose bool) error {
var data models.APIResponse
var err error
var cursor string

var requestMethod string
var requestPath string
var requestHeaders http.Header
var responseHeaders http.Header
var responseStatusCode int
var protocol string

isExtensionsLiveEndpoint := false // https://github.com/twitchdev/twitch-cli/issues/157

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

if runCounter == 1 {
data = apiResponse

requestMethod = resp.HttpMethod
requestPath = resp.RequestPath
responseStatusCode = resp.StatusCode
requestHeaders = resp.RequestHeaders
responseHeaders = resp.ResponseHeaders
protocol = resp.HttpVersion
}

if resp.StatusCode > 299 || resp.StatusCode < 200 {
Expand Down Expand Up @@ -210,6 +224,10 @@ func NewRequest(method string, path string, queryParameters []string, body []byt
// since Command Prompt/Powershell don't support coloring, will pretty print without colors
if runtime.GOOS == "windows" {
s, _ := json.MarshalIndent(obj, "", " ")

if verbose {
printVerboseHeaders(requestMethod, requestPath, requestHeaders, responseHeaders, responseStatusCode, protocol)
}
if data.Error == "" {
fmt.Println(string(s))
} else {
Expand All @@ -226,6 +244,10 @@ func NewRequest(method string, path string, queryParameters []string, body []byt
if err != nil {
return err
}

if verbose {
printVerboseHeaders(requestMethod, requestPath, requestHeaders, responseHeaders, responseStatusCode, protocol)
}
if data.Error == "" {
fmt.Println(string(s))
} else {
Expand All @@ -234,6 +256,9 @@ func NewRequest(method string, path string, queryParameters []string, body []byt
return nil
}

if verbose {
printVerboseHeaders(requestMethod, requestPath, requestHeaders, responseHeaders, responseStatusCode, protocol)
}
if data.Error == "" {
fmt.Println(string(d))
} else {
Expand Down Expand Up @@ -297,3 +322,31 @@ func GetClientInformation() (clientInformation, error) {

return clientInformation{Token: token, ClientID: clientID}, nil
}

func printVerboseHeaders(method string, path string, requestHeaders http.Header, responseHeaders http.Header, responseStatusCode int, protocol string) {
fmt.Printf("* Using %v\n", protocol)
fmt.Printf("> %v %v\n", method, path)
for key, value := range requestHeaders {
for _, v := range value {
if strings.EqualFold(key, "authorization") {
parts := strings.Split(v, " ")
if len(parts) > 1 {
fmt.Printf("> %v: %v *****\n", key, parts[0])
} else {
fmt.Printf("> %v: *****\n", key)
}
} else {
fmt.Printf("> %v: %v\n", key, v)
}
}
}

fmt.Printf("\n")
fmt.Printf("< %v %v %v\n", protocol, responseStatusCode, http.StatusText(responseStatusCode))
for key, value := range responseHeaders {
for _, v := range value {
fmt.Printf("< %v: %v\n", key, v)
}
}
fmt.Printf("\n")
}
13 changes: 13 additions & 0 deletions internal/api/api_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"time"

"github.com/twitchdev/twitch-cli/internal/request"
Expand All @@ -19,6 +20,12 @@ type apiRequestParameters struct {
type apiRequestResponse struct {
StatusCode int
Body []byte

HttpMethod string
RequestPath string
RequestHeaders http.Header
ResponseHeaders http.Header
HttpVersion string
}

func apiRequest(method string, url string, payload []byte, p apiRequestParameters) (apiRequestResponse, error) {
Expand Down Expand Up @@ -54,5 +61,11 @@ func apiRequest(method string, url string, payload []byte, p apiRequestParameter
return apiRequestResponse{
StatusCode: resp.StatusCode,
Body: body,

HttpMethod: req.Method,
RequestPath: req.URL.RequestURI(),
RequestHeaders: req.Header,
ResponseHeaders: resp.Header,
HttpVersion: req.Proto,
}, nil
}
10 changes: 5 additions & 5 deletions internal/api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,17 @@ func TestNewRequest(t *testing.T) {

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

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

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

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

func TestValidOptions(t *testing.T) {
Expand Down

0 comments on commit 2404139

Please sign in to comment.