Skip to content

Commit 62ffc68

Browse files
committed
Refactor DoRequest function to handle idempotent and non-idempotent HTTP methods
1 parent bfd02f1 commit 62ffc68

File tree

1 file changed

+53
-8
lines changed

1 file changed

+53
-8
lines changed

httpclient/httpclient_request.go

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,52 @@ import (
1313
"go.uber.org/zap"
1414
)
1515

16-
// DoRequest constructs and executes an HTTP request, choosing the execution path based on the idempotency of the HTTP method.
16+
// DoRequest constructs and executes an HTTP request based on the provided method, endpoint, request body, and output variable.
17+
// This function serves as a dispatcher, deciding whether to execute the request with or without retry logic based on the
18+
// idempotency of the HTTP method. Idempotent methods (GET, PUT, DELETE) are executed with retries to handle transient errors
19+
// and rate limits, while non-idempotent methods (POST, PATCH) are executed without retries to avoid potential side effects
20+
// of duplicating non-idempotent operations.
21+
22+
// Parameters:
23+
// - method: A string representing the HTTP method to be used for the request. This method determines the execution path
24+
// and whether the request will be retried in case of failures.
25+
// - endpoint: The target API endpoint for the request. This should be a relative path that will be appended to the base URL
26+
// configured for the HTTP client.
27+
// - body: The payload for the request, which will be serialized into the request body. The serialization format (e.g., JSON, XML)
28+
// is determined by the content-type header and the specific implementation of the API handler used by the client.
29+
// - out: A pointer to an output variable where the response will be deserialized. The function expects this to be a pointer to
30+
// a struct that matches the expected response schema.
31+
// - log: An instance of a logger implementing the logger.Logger interface, used to log informational messages, warnings, and
32+
// errors encountered during the execution of the request.
33+
34+
// Returns:
35+
// - *http.Response: The HTTP response received from the server. In case of successful execution, this response contains
36+
// the status code, headers, and body of the response. In case of errors, particularly after exhausting retries for
37+
// idempotent methods, this response may contain the last received HTTP response that led to the failure.
38+
// - error: An error object indicating failure during request execution. This could be due to network issues, server errors,
39+
// or a failure in request serialization/deserialization. For idempotent methods, an error is returned if all retries are
40+
// exhausted without success.
41+
42+
// Usage:
43+
// This function is the primary entry point for executing HTTP requests using the client. It abstracts away the details of
44+
// request retries, serialization, and response handling, providing a simplified interface for making HTTP requests. It is
45+
// suitable for a wide range of HTTP operations, from fetching data with GET requests to submitting data with POST requests.
46+
47+
// Example:
48+
// var result MyResponseType
49+
// resp, err := client.DoRequest("GET", "/api/resource", nil, &result, logger)
50+
// if err != nil {
51+
// // Handle error
52+
// }
53+
// // Use `result` or `resp` as needed
54+
55+
// Note:
56+
// - The caller is responsible for closing the response body when not nil to avoid resource leaks.
57+
// - The function ensures concurrency control by managing concurrency tokens internally, providing safe concurrent operations
58+
// within the client's concurrency model.
59+
// - The decision to retry requests is based on the idempotency of the HTTP method and the client's retry configuration,
60+
// including maximum retry attempts and total retry duration.
61+
1762
func (c *Client) DoRequest(method, endpoint string, body, out interface{}, log logger.Logger) (*http.Response, error) {
1863
if IsIdempotentHTTPMethod(method) {
1964
return c.executeRequestWithRetries(method, endpoint, body, out, log)
@@ -213,9 +258,9 @@ func (c *Client) executeRequest(method, endpoint string, body, out interface{},
213258
url := c.APIHandler.ConstructAPIResourceEndpoint(c.InstanceName, endpoint, log)
214259

215260
// Initialize total request counter
216-
c.PerfMetrics.lock.Lock()
217-
c.PerfMetrics.TotalRequests++
218-
c.PerfMetrics.lock.Unlock()
261+
//c.PerfMetrics.lock.Lock()
262+
//c.PerfMetrics.TotalRequests++
263+
//c.PerfMetrics.lock.Unlock()
219264

220265
// Perform Request
221266
req, err := http.NewRequest(method, url, bytes.NewBuffer(requestData))
@@ -229,8 +274,8 @@ func (c *Client) executeRequest(method, endpoint string, body, out interface{},
229274
headerManager.LogHeaders(c)
230275

231276
// Start response time measurement
232-
responseTimeStart := time.Now()
233-
// For non-retryable HTTP Methods (POST - Create)
277+
//responseTimeStart := time.Now()
278+
// Set the context with the request ID
234279
req = req.WithContext(ctx)
235280

236281
// Execute the HTTP request
@@ -240,8 +285,8 @@ func (c *Client) executeRequest(method, endpoint string, body, out interface{},
240285
}
241286

242287
// After each request, compute and update response time
243-
responseDuration := time.Since(responseTimeStart)
244-
c.updatePerformanceMetrics(responseDuration)
288+
//responseDuration := time.Since(responseTimeStart)
289+
//c.updatePerformanceMetrics(responseDuration)
245290

246291
// Checks for the presence of a deprecation header in the HTTP response and logs if found.
247292
CheckDeprecationHeader(resp, log)

0 commit comments

Comments
 (0)