Skip to content

Commit 4f3dbed

Browse files
authored
Merge pull request #130 from deploymenttheory/dev
Changed error handling behaviour and removed redundant cookie handling functions
2 parents 82d081e + 85c720a commit 4f3dbed

File tree

4 files changed

+130
-141
lines changed

4 files changed

+130
-141
lines changed

cookiejar/cookiejar.go

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"fmt"
1313
"net/http"
1414
"net/http/cookiejar"
15-
"net/url"
1615
"strings"
1716

1817
"github.com/deploymenttheory/go-api-http-client/logger"
@@ -32,6 +31,35 @@ func SetupCookieJar(client *http.Client, enableCookieJar bool, log logger.Logger
3231
return nil
3332
}
3433

34+
// GetCookies is a middleware that extracts cookies from incoming requests and serializes them.
35+
func GetCookies(next http.Handler, log logger.Logger) http.Handler {
36+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
37+
38+
// Extract cookies from the request
39+
cookies := r.Cookies()
40+
41+
// Serialize the cookies
42+
serializedCookies := SerializeCookies(cookies)
43+
44+
// Log the serialized cookies
45+
log.Info("Serialized Cookies", zap.String("Cookies", serializedCookies))
46+
47+
// Call the next handler in the chain
48+
next.ServeHTTP(w, r)
49+
})
50+
}
51+
52+
// SerializeCookies serializes a slice of *http.Cookie into a string format.
53+
func SerializeCookies(cookies []*http.Cookie) string {
54+
var cookieStrings []string
55+
56+
for _, cookie := range cookies {
57+
cookieStrings = append(cookieStrings, cookie.String())
58+
}
59+
60+
return strings.Join(cookieStrings, "; ")
61+
}
62+
3563
// RedactSensitiveCookies redacts sensitive information from cookies.
3664
// It takes a slice of *http.Cookie and returns a redacted slice of *http.Cookie.
3765
func RedactSensitiveCookies(cookies []*http.Cookie) []*http.Cookie {
@@ -74,28 +102,3 @@ func ParseCookieHeader(header string) *http.Cookie {
74102
}
75103
return nil
76104
}
77-
78-
// PrintCookies prints the cookies stored in the HTTP client's cookie jar for a given URL.
79-
func PrintCookies(client *http.Client, urlString string, log logger.Logger) {
80-
if client.Jar == nil {
81-
log.Error("Cookie jar is not initialized.")
82-
return
83-
}
84-
85-
// Correctly use url.Parse for parsing the URL string
86-
parsedURL, err := url.Parse(urlString)
87-
if err != nil {
88-
log.Error("Failed to parse URL for cookie jar", zap.Error(err))
89-
return
90-
}
91-
92-
cookies := client.Jar.Cookies(parsedURL)
93-
if len(cookies) == 0 {
94-
log.Info("No cookies found for URL", zap.String("url", urlString))
95-
return
96-
}
97-
98-
for _, cookie := range cookies {
99-
log.Info("Cookie", zap.String("Name", cookie.Name), zap.String("Value", cookie.Value))
100-
}
101-
}

headers/headers.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,6 @@ func NewHeaderHandler(req *http.Request, log logger.Logger, apiHandler apihandle
3232
}
3333
}
3434

35-
// func (h *HeaderHandler) SetAuthorization(token string) {
36-
// // Ensure the token is prefixed with "Bearer " only once
37-
// if !strings.HasPrefix(token, "Bearer ") {
38-
// token = "Bearer " + token
39-
// }
40-
// h.req.Header.Set("Authorization", token)
41-
// }
42-
4335
// SetAuthorization sets the Authorization header for the request.
4436
func (h *HeaderHandler) SetAuthorization() {
4537
token := h.authTokenHandler.Token

httpclient/multipartrequest.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// httprequest/multipartrequest.go
2+
package httpclient
3+
4+
import (
5+
"bytes"
6+
"net/http"
7+
8+
"github.com/deploymenttheory/go-api-http-client/authenticationhandler"
9+
"github.com/deploymenttheory/go-api-http-client/headers"
10+
)
11+
12+
// DoMultipartRequest creates and executes a multipart HTTP request. It is used for sending files
13+
// and form fields in a single request. This method handles the construction of the multipart
14+
// message body, setting the appropriate headers, and sending the request to the given endpoint.
15+
//
16+
// Parameters:
17+
// - method: The HTTP method to use (e.g., POST, PUT).
18+
// - endpoint: The API endpoint to which the request will be sent.
19+
// - fields: A map of form fields and their values to include in the multipart message.
20+
// - files: A map of file field names to file paths that will be included as file attachments.
21+
// - out: A pointer to a variable where the unmarshaled response will be stored.
22+
//
23+
// Returns:
24+
// - A pointer to the http.Response received from the server.
25+
// - An error if the request could not be sent or the response could not be processed.
26+
//
27+
// The function first validates the authentication token, then constructs the multipart
28+
// request body based on the provided fields and files. It then constructs the full URL for
29+
// the request, sets the required headers (including Authorization and Content-Type), and
30+
// sends the request.
31+
//
32+
// If debug mode is enabled, the function logs all the request headers before sending the request.
33+
// After the request is sent, the function checks the response status code. If the response is
34+
// not within the success range (200-299), it logs an error and returns the response and an error.
35+
// If the response is successful, it attempts to unmarshal the response body into the 'out' parameter.
36+
//
37+
// Note:
38+
// The caller should handle closing the response body when successful.
39+
func (c *Client) DoMultipartRequest(method, endpoint string, fields map[string]string, files map[string]string, out interface{}) (*http.Response, error) {
40+
log := c.Logger
41+
42+
// Auth Token validation check
43+
clientCredentials := authenticationhandler.ClientCredentials{
44+
Username: c.clientConfig.Auth.Username,
45+
Password: c.clientConfig.Auth.Password,
46+
ClientID: c.clientConfig.Auth.ClientID,
47+
ClientSecret: c.clientConfig.Auth.ClientSecret,
48+
}
49+
50+
valid, err := c.AuthTokenHandler.ValidAuthTokenCheck(c.APIHandler, c.httpClient, clientCredentials, c.clientConfig.ClientOptions.TokenRefreshBufferPeriod)
51+
if err != nil || !valid {
52+
return nil, err
53+
}
54+
55+
// Marshal the multipart form data
56+
requestData, contentType, err := c.APIHandler.MarshalMultipartRequest(fields, files, log)
57+
if err != nil {
58+
return nil, err
59+
}
60+
61+
// Construct URL using the ConstructAPIResourceEndpoint function
62+
url := c.APIHandler.ConstructAPIResourceEndpoint(c.InstanceName, endpoint, log)
63+
64+
// Create the request
65+
req, err := http.NewRequest(method, url, bytes.NewBuffer(requestData))
66+
if err != nil {
67+
return nil, err
68+
}
69+
70+
// Initialize HeaderManager
71+
//log.Debug("Setting Authorization header with token", zap.String("Token", c.Token))
72+
headerHandler := headers.NewHeaderHandler(req, c.Logger, c.APIHandler, c.AuthTokenHandler)
73+
74+
// Use HeaderManager to set headers
75+
headerHandler.SetContentType(contentType)
76+
headerHandler.SetRequestHeaders(endpoint)
77+
headerHandler.LogHeaders(c.clientConfig.ClientOptions.HideSensitiveData)
78+
79+
// Execute the request
80+
resp, err := c.do(req, log, method, endpoint)
81+
if err != nil {
82+
return nil, err
83+
}
84+
85+
// Check for successful status code
86+
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
87+
// Handle error responses
88+
//return nil, c.handleErrorResponse(resp, log, "Failed to process the HTTP request", method, endpoint)
89+
return nil, c.handleErrorResponse(resp, out, log, method, endpoint)
90+
} else {
91+
// Handle successful responses
92+
return resp, c.handleSuccessResponse(resp, out, log, method, endpoint)
93+
}
94+
}

httpclient/request.go

Lines changed: 7 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ func (c *Client) executeRequestWithRetries(method, endpoint string, body, out in
153153
c.ConcurrencyHandler.Metrics.TotalRequests++
154154
c.ConcurrencyHandler.Metrics.Lock.Unlock()
155155

156-
// Perform Request
156+
// Create a new HTTP request with the provided method, URL, and body
157157
req, err := http.NewRequest(method, url, bytes.NewBuffer(requestData))
158158
if err != nil {
159159
return nil, err
@@ -314,7 +314,7 @@ func (c *Client) executeRequest(method, endpoint string, body, out interface{})
314314
// Construct URL using the ConstructAPIResourceEndpoint function
315315
url := c.APIHandler.ConstructAPIResourceEndpoint(c.InstanceName, endpoint, log)
316316

317-
// Perform Request
317+
// Create a new HTTP request with the provided method, URL, and body
318318
req, err := http.NewRequest(method, url, bytes.NewBuffer(requestData))
319319
if err != nil {
320320
return nil, err
@@ -336,7 +336,7 @@ func (c *Client) executeRequest(method, endpoint string, body, out interface{})
336336
return nil, err
337337
}
338338

339-
// Log incoming cookies
339+
// Log outgoing cookies
340340
log.LogCookies("incoming", req, method, endpoint)
341341

342342
// Checks for the presence of a deprecation header in the HTTP response and logs if found.
@@ -352,7 +352,8 @@ func (c *Client) executeRequest(method, endpoint string, body, out interface{})
352352
}
353353

354354
// Handle error responses for status codes outside the successful range
355-
return nil, c.handleErrorResponse(resp, out, log, method, endpoint)
355+
//return nil, c.handleErrorResponse(resp, out, log, method, endpoint)
356+
return nil, response.HandleAPIErrorResponse(resp, log)
356357
}
357358

358359
// do sends an HTTP request using the client's HTTP client. It logs the request and error details, if any,
@@ -378,20 +379,12 @@ func (c *Client) do(req *http.Request, log logger.Logger, method, endpoint strin
378379

379380
if err != nil {
380381
// Log the error with structured logging, including method, endpoint, and the error itself
381-
log.Error("Failed to send request",
382-
zap.String("method", method),
383-
zap.String("endpoint", endpoint),
384-
zap.Error(err),
385-
)
382+
log.Error("Failed to send request", zap.String("method", method), zap.String("endpoint", endpoint), zap.Error(err))
386383
return nil, err
387384
}
388385

389386
// Log the response status code for successful requests
390-
log.Debug("Request sent successfully",
391-
zap.String("method", method),
392-
zap.String("endpoint", endpoint),
393-
zap.Int("status_code", resp.StatusCode),
394-
)
387+
log.Debug("Request sent successfully", zap.String("method", method), zap.String("endpoint", endpoint), zap.Int("status_code", resp.StatusCode))
395388

396389
return resp, nil
397390
}
@@ -453,96 +446,3 @@ func (c *Client) handleSuccessResponse(resp *http.Response, out interface{}, log
453446
)
454447
return nil
455448
}
456-
457-
// DoMultipartRequest creates and executes a multipart HTTP request. It is used for sending files
458-
// and form fields in a single request. This method handles the construction of the multipart
459-
// message body, setting the appropriate headers, and sending the request to the given endpoint.
460-
//
461-
// Parameters:
462-
// - method: The HTTP method to use (e.g., POST, PUT).
463-
// - endpoint: The API endpoint to which the request will be sent.
464-
// - fields: A map of form fields and their values to include in the multipart message.
465-
// - files: A map of file field names to file paths that will be included as file attachments.
466-
// - out: A pointer to a variable where the unmarshaled response will be stored.
467-
//
468-
// Returns:
469-
// - A pointer to the http.Response received from the server.
470-
// - An error if the request could not be sent or the response could not be processed.
471-
//
472-
// The function first validates the authentication token, then constructs the multipart
473-
// request body based on the provided fields and files. It then constructs the full URL for
474-
// the request, sets the required headers (including Authorization and Content-Type), and
475-
// sends the request.
476-
//
477-
// If debug mode is enabled, the function logs all the request headers before sending the request.
478-
// After the request is sent, the function checks the response status code. If the response is
479-
// not within the success range (200-299), it logs an error and returns the response and an error.
480-
// If the response is successful, it attempts to unmarshal the response body into the 'out' parameter.
481-
//
482-
// Note:
483-
// The caller should handle closing the response body when successful.
484-
func (c *Client) DoMultipartRequest(method, endpoint string, fields map[string]string, files map[string]string, out interface{}) (*http.Response, error) {
485-
log := c.Logger
486-
487-
// Auth Token validation check
488-
// valid, err := c.ValidAuthTokenCheck()
489-
// if err != nil || !valid {
490-
// return nil, err
491-
//}
492-
493-
// Auth Token validation check
494-
clientCredentials := authenticationhandler.ClientCredentials{
495-
Username: c.clientConfig.Auth.Username,
496-
Password: c.clientConfig.Auth.Password,
497-
ClientID: c.clientConfig.Auth.ClientID,
498-
ClientSecret: c.clientConfig.Auth.ClientSecret,
499-
}
500-
501-
valid, err := c.AuthTokenHandler.ValidAuthTokenCheck(c.APIHandler, c.httpClient, clientCredentials, c.clientConfig.ClientOptions.TokenRefreshBufferPeriod)
502-
if err != nil || !valid {
503-
return nil, err
504-
}
505-
506-
// Determine which set of encoding and content-type request rules to use
507-
//apiHandler := c.APIHandler
508-
509-
// Marshal the multipart form data
510-
requestData, contentType, err := c.APIHandler.MarshalMultipartRequest(fields, files, log)
511-
if err != nil {
512-
return nil, err
513-
}
514-
515-
// Construct URL using the ConstructAPIResourceEndpoint function
516-
url := c.APIHandler.ConstructAPIResourceEndpoint(c.InstanceName, endpoint, log)
517-
518-
// Create the request
519-
req, err := http.NewRequest(method, url, bytes.NewBuffer(requestData))
520-
if err != nil {
521-
return nil, err
522-
}
523-
524-
// Initialize HeaderManager
525-
//log.Debug("Setting Authorization header with token", zap.String("Token", c.Token))
526-
headerHandler := headers.NewHeaderHandler(req, c.Logger, c.APIHandler, c.AuthTokenHandler)
527-
528-
// Use HeaderManager to set headers
529-
headerHandler.SetContentType(contentType)
530-
headerHandler.SetRequestHeaders(endpoint)
531-
headerHandler.LogHeaders(c.clientConfig.ClientOptions.HideSensitiveData)
532-
533-
// Execute the request
534-
resp, err := c.do(req, log, method, endpoint)
535-
if err != nil {
536-
return nil, err
537-
}
538-
539-
// Check for successful status code
540-
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
541-
// Handle error responses
542-
//return nil, c.handleErrorResponse(resp, log, "Failed to process the HTTP request", method, endpoint)
543-
return nil, c.handleErrorResponse(resp, out, log, method, endpoint)
544-
} else {
545-
// Handle successful responses
546-
return resp, c.handleSuccessResponse(resp, out, log, method, endpoint)
547-
}
548-
}

0 commit comments

Comments
 (0)