Skip to content

Commit 6b2818d

Browse files
committed
Refactor API client to consolidate request options and add trace support in request handling.
1 parent 0974a81 commit 6b2818d

6 files changed

Lines changed: 58 additions & 60 deletions

File tree

api/client.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type RequestOptions struct {
2929
AuthType string
3030
Username string
3131
Verbose bool
32+
Trace bool
3233
}
3334

3435
// MultipartOptions contains options specific to multipart requests
@@ -44,7 +45,7 @@ type MultipartOptions struct {
4445
// Client is an interface for API clients
4546
type Client interface {
4647
GetAuthHeader(method, url string, authType string, username string) (string, error)
47-
BuildRequest(method, endpoint string, headers []string, body io.Reader, contentType string, authType string, username string) (*http.Request, error)
48+
BuildRequest(requestOptions RequestOptions, body io.Reader, contentType string) (*http.Request, error)
4849
SendRequest(options RequestOptions) (json.RawMessage, error)
4950
StreamRequest(options RequestOptions) error
5051
SendMultipartRequest(options MultipartOptions) (json.RawMessage, error)
@@ -114,19 +115,19 @@ func (c *ApiClient) GetAuthHeader(method, url string, authType string, username
114115
}
115116

116117
// BuildRequest builds an HTTP request
117-
func (c *ApiClient) BuildRequest(method, endpoint string, headers []string, body io.Reader, contentType string, authType string, username string) (*http.Request, error) {
118-
httpMethod := strings.ToUpper(method)
118+
func (c *ApiClient) BuildRequest(requestOptions RequestOptions, body io.Reader, contentType string) (*http.Request, error) {
119+
httpMethod := strings.ToUpper(requestOptions.Method)
119120

120-
url := endpoint
121-
if !strings.HasPrefix(strings.ToLower(endpoint), "http") {
121+
url := requestOptions.Endpoint
122+
if !strings.HasPrefix(strings.ToLower(requestOptions.Endpoint), "http") {
122123
url = c.url
123124
if !strings.HasSuffix(url, "/") {
124125
url += "/"
125126
}
126-
if strings.HasPrefix(endpoint, "/") {
127-
url += endpoint[1:]
127+
if strings.HasPrefix(requestOptions.Endpoint, "/") {
128+
url += requestOptions.Endpoint[1:]
128129
} else {
129-
url += endpoint
130+
url += requestOptions.Endpoint
130131
}
131132
}
132133

@@ -135,7 +136,7 @@ func (c *ApiClient) BuildRequest(method, endpoint string, headers []string, body
135136
return nil, xurlErrors.NewHTTPError(err)
136137
}
137138

138-
for _, header := range headers {
139+
for _, header := range requestOptions.Headers {
139140
parts := strings.SplitN(header, ":", 2)
140141
if len(parts) == 2 {
141142
req.Header.Add(strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]))
@@ -147,14 +148,18 @@ func (c *ApiClient) BuildRequest(method, endpoint string, headers []string, body
147148
}
148149

149150
if req.Header.Get("Authorization") == "" {
150-
authHeader, err := c.GetAuthHeader(httpMethod, url, authType, username)
151+
authHeader, err := c.GetAuthHeader(httpMethod, url, requestOptions.AuthType, requestOptions.Username)
151152
if err == nil {
152153
req.Header.Add("Authorization", authHeader)
153154
}
154155
}
155156

156157
req.Header.Add("User-Agent", "xurl/"+version.Version)
157158

159+
if requestOptions.Trace {
160+
req.Header.Add("X-B3-Flags", "1")
161+
}
162+
158163
return req, nil
159164
}
160165

@@ -221,7 +226,7 @@ func (c *ApiClient) SendRequest(options RequestOptions) (json.RawMessage, error)
221226
}
222227
}
223228

224-
req, err := c.BuildRequest(options.Method, options.Endpoint, options.Headers, body, contentType, options.AuthType, options.Username)
229+
req, err := c.BuildRequest(options, body, contentType)
225230

226231
if err != nil {
227232
return nil, xurlErrors.NewHTTPError(err)
@@ -280,7 +285,7 @@ func (c *ApiClient) SendMultipartRequest(options MultipartOptions) (json.RawMess
280285
return nil, xurlErrors.NewIOError(fmt.Errorf("error closing multipart writer: %v", err))
281286
}
282287

283-
req, err := c.BuildRequest(options.Method, options.Endpoint, options.Headers, body, writer.FormDataContentType(), options.AuthType, options.Username)
288+
req, err := c.BuildRequest(options.RequestOptions, body, writer.FormDataContentType())
284289
if err != nil {
285290
return nil, xurlErrors.NewHTTPError(err)
286291
}
@@ -312,7 +317,7 @@ func (c *ApiClient) StreamRequest(options RequestOptions) error {
312317
}
313318
}
314319

315-
req, err := c.BuildRequest(options.Method, options.Endpoint, options.Headers, body, contentType, options.AuthType, options.Username)
320+
req, err := c.BuildRequest(options, body, contentType)
316321
if err != nil {
317322
return xurlErrors.NewHTTPError(err)
318323
}

api/client_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,15 @@ func TestBuildRequest(t *testing.T) {
149149
}
150150
}
151151

152-
req, err := client.BuildRequest(tt.method, tt.endpoint, tt.headers, body, contentType, tt.authType, tt.username)
152+
requestOptions := RequestOptions{
153+
Method: tt.method,
154+
Endpoint: tt.endpoint,
155+
Headers: tt.headers,
156+
AuthType: tt.authType,
157+
Username: tt.username,
158+
}
159+
160+
req, err := client.BuildRequest(requestOptions, body, contentType)
153161

154162
if tt.wantErr {
155163
assert.Error(t, err)

api/execute.go

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,7 @@ import (
77
)
88

99
// ExecuteRequest handles the execution of a regular API request
10-
func ExecuteRequest(method, url string, headers []string, data, authType, username string, verbose bool, client Client) error {
11-
options := RequestOptions{
12-
Method: method,
13-
Endpoint: url,
14-
Headers: headers,
15-
Data: data,
16-
AuthType: authType,
17-
Username: username,
18-
Verbose: verbose,
19-
}
10+
func ExecuteRequest(options RequestOptions, client Client) error {
2011

2112
response, clientErr := client.SendRequest(options)
2213
if clientErr != nil {
@@ -27,16 +18,7 @@ func ExecuteRequest(method, url string, headers []string, data, authType, userna
2718
}
2819

2920
// ExecuteStreamRequest handles the execution of a streaming API request
30-
func ExecuteStreamRequest(method, url string, headers []string, data, authType, username string, verbose bool, client Client) error {
31-
options := RequestOptions{
32-
Method: method,
33-
Endpoint: url,
34-
Headers: headers,
35-
Data: data,
36-
AuthType: authType,
37-
Username: username,
38-
Verbose: verbose,
39-
}
21+
func ExecuteStreamRequest(options RequestOptions, client Client) error {
4022

4123
clientErr := client.StreamRequest(options)
4224
if clientErr != nil {
@@ -57,21 +39,21 @@ func handleRequestError(clientErr error) error {
5739
// formatAndPrintResponse formats and prints API responses
5840

5941
// HandleRequest determines the type of request and executes it accordingly
60-
func HandleRequest(method, url string, headers []string, data, authType, username string, verbose, forceStream bool, mediaFile string, client Client) error {
61-
if IsMediaAppendRequest(url, mediaFile) {
62-
response, err := HandleMediaAppendRequest(url, mediaFile, method, headers, data, authType, username, verbose, client)
42+
func HandleRequest(options RequestOptions, forceStream bool, mediaFile string, client Client) error {
43+
if IsMediaAppendRequest(options.Endpoint, mediaFile) {
44+
response, err := HandleMediaAppendRequest(options, mediaFile, client)
6345
if err != nil {
6446
return err
6547
}
6648

6749
return utils.FormatAndPrintResponse(response)
6850
}
6951

70-
shouldStream := forceStream || IsStreamingEndpoint(url)
52+
shouldStream := forceStream || IsStreamingEndpoint(options.Endpoint)
7153

7254
if shouldStream {
73-
return ExecuteStreamRequest(method, url, headers, data, authType, username, verbose, client)
55+
return ExecuteStreamRequest(options, client)
7456
} else {
75-
return ExecuteRequest(method, url, headers, data, authType, username, verbose, client)
57+
return ExecuteRequest(options, client)
7658
}
7759
}

api/media.go

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -385,13 +385,13 @@ func ExecuteMediaStatus(mediaID, authType, username string, verbose, wait bool,
385385
}
386386

387387
// HandleMediaAppendRequest handles a media append request with a file
388-
func HandleMediaAppendRequest(url, mediaFile, method string, headers []string, data, authType, username string, verbose bool, client Client) (json.RawMessage, error) {
389-
mediaID := ExtractMediaID(url, data)
388+
func HandleMediaAppendRequest(options RequestOptions, mediaFile string, client Client) (json.RawMessage, error) {
389+
mediaID := ExtractMediaID(options.Endpoint, options.Data)
390390
if mediaID == "" {
391391
return nil, fmt.Errorf("media_id is required for APPEND command")
392392
}
393393

394-
segmentIndex := ExtractSegmentIndex(url, data)
394+
segmentIndex := ExtractSegmentIndex(options.Endpoint, options.Data)
395395
if segmentIndex == "" {
396396
segmentIndex = "0"
397397
}
@@ -402,17 +402,8 @@ func HandleMediaAppendRequest(url, mediaFile, method string, headers []string, d
402402
"segment_index": segmentIndex,
403403
}
404404

405-
requestOptions := RequestOptions{
406-
Method: method,
407-
Endpoint: url,
408-
Headers: headers,
409-
Data: data,
410-
AuthType: authType,
411-
Username: username,
412-
Verbose: verbose,
413-
}
414405
multipartOptions := MultipartOptions{
415-
RequestOptions: requestOptions,
406+
RequestOptions: options,
416407
FormFields: formFields,
417408
FileField: "media",
418409
FilePath: mediaFile,

api/media_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ func (m *MockApiClient) SendMultipartRequest(options MultipartOptions) (json.Raw
2929
return args.Get(0).(json.RawMessage), args.Error(1)
3030
}
3131

32-
func (m *MockApiClient) BuildRequest(method, endpoint string, headers []string, data io.Reader, contentType string, authType string, username string) (*http.Request, error) {
33-
args := m.Called(method, endpoint, headers, data, contentType, authType, username)
32+
func (m *MockApiClient) BuildRequest(requestOptions RequestOptions, body io.Reader, contentType string) (*http.Request, error) {
33+
args := m.Called(requestOptions, body, contentType)
3434
return args.Get(0).(*http.Request), args.Error(1)
3535
}
3636

@@ -563,16 +563,17 @@ func TestHandleMediaAppendRequest(t *testing.T) {
563563
}
564564
mockClient.On("SendMultipartRequest", multipartOptions).Return(mockResponse, nil).Twice()
565565

566-
response, err := HandleMediaAppendRequest(url, tempFile, "POST", []string{}, "", "oauth2", "testuser", false, mockClient)
566+
response, err := HandleMediaAppendRequest(requestOptions, tempFile, mockClient)
567567
assert.NoError(t, err)
568568
assert.Equal(t, mockResponse, response)
569569

570-
response, err = HandleMediaAppendRequest(url, tempFile, "POST", []string{}, "", "oauth2", "testuser", false, mockClient)
570+
response, err = HandleMediaAppendRequest(requestOptions, tempFile, mockClient)
571571
assert.NoError(t, err)
572572
assert.Equal(t, mockResponse, response)
573573

574-
url = "/2/media/upload?command=APPEND"
575-
response, err = HandleMediaAppendRequest(url, tempFile, "POST", []string{}, "", "oauth2", "testuser", false, mockClient)
574+
requestOptionsNoMediaID := requestOptions
575+
requestOptionsNoMediaID.Endpoint = "/2/media/upload?command=APPEND"
576+
response, err = HandleMediaAppendRequest(requestOptionsNoMediaID, tempFile, mockClient)
576577
assert.Error(t, err)
577578
assert.Contains(t, err.Error(), "media_id is required")
578579
assert.Nil(t, response)

cli/root.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Examples:
4242
authType, _ := cmd.Flags().GetString("auth")
4343
username, _ := cmd.Flags().GetString("username")
4444
verbose, _ := cmd.Flags().GetBool("verbose")
45+
trace, _ := cmd.Flags().GetBool("trace")
4546
forceStream, _ := cmd.Flags().GetBool("stream")
4647
mediaFile, _ := cmd.Flags().GetString("file")
4748

@@ -56,7 +57,17 @@ Examples:
5657

5758
client := api.NewApiClient(config, auth)
5859

59-
err := api.HandleRequest(method, url, headers, data, authType, username, verbose, forceStream, mediaFile, client)
60+
requestOptions := api.RequestOptions{
61+
Method: method,
62+
Endpoint: url,
63+
Headers: headers,
64+
Data: data,
65+
AuthType: authType,
66+
Username: username,
67+
Verbose: verbose,
68+
Trace: trace,
69+
}
70+
err := api.HandleRequest(requestOptions, forceStream, mediaFile, client)
6071
if err != nil {
6172
fmt.Printf("\033[31mError: %v\033[0m\n", err)
6273
os.Exit(1)

0 commit comments

Comments
 (0)