From 73236b1a09c28d0355fcbf257cd930a81e6a7a35 Mon Sep 17 00:00:00 2001 From: ShocOne <62835948+ShocOne@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:05:58 +0000 Subject: [PATCH 1/2] Refactor API response handling in JamfPro and HttpClient*** --- apihandlers/jamfpro/jamfpro_api_response.go | 57 +++++++++++++++++++++ httpclient/httpclient_api_handler.go | 4 +- httpclient/httpclient_request.go | 18 +------ 3 files changed, 62 insertions(+), 17 deletions(-) diff --git a/apihandlers/jamfpro/jamfpro_api_response.go b/apihandlers/jamfpro/jamfpro_api_response.go index b836991..26c19e5 100644 --- a/apihandlers/jamfpro/jamfpro_api_response.go +++ b/apihandlers/jamfpro/jamfpro_api_response.go @@ -14,6 +14,63 @@ import ( ) // Functions +func (j *JamfAPIHandler) HandleAPISuccessResponse(resp *http.Response, out interface{}, log logger.Logger) error { + // Special handling for DELETE requests + if resp.Request.Method == "DELETE" { + return j.handleDeleteRequest(resp) + } + + // Read the response body + bodyBytes, err := j.readResponseBody(resp) + if err != nil { + return err + } + + // Log the raw response details for debugging + j.logResponseDetails(resp, bodyBytes) + + // Unmarshal the response based on content type + contentType := resp.Header.Get("Content-Type") + + // Check for binary data handling + contentDisposition := resp.Header.Get("Content-Disposition") + if err := j.handleBinaryData(contentType, contentDisposition, bodyBytes, out); err != nil { + return err + } + + return j.unmarshalResponse(contentType, bodyBytes, out) +} + +func (j *JamfAPIHandler) HandleAPIErrorResponse(resp *http.Response, out interface{}, log logger.Logger) error { + // Read the response body + bodyBytes, err := j.readResponseBody(resp) + if err != nil { + return err + } + + // Convert bodyBytes to a string to represent the raw response body + rawResponse := string(bodyBytes) + + // Log the raw response details for debugging + j.logResponseDetails(resp, bodyBytes) + + // Get the content type from the response headers + contentType := resp.Header.Get("Content-Type") + + // Handle known error content types (e.g., JSON, HTML) + if strings.Contains(contentType, "application/json") { + return j.handleErrorJSONResponse(bodyBytes, resp.StatusCode, rawResponse) + } else if strings.Contains(contentType, "text/html") { + return j.handleErrorHTMLResponse(bodyBytes, resp.StatusCode) + } + + // Generic error handling for unknown content types + j.Logger.Error("Received non-success status code without detailed error response", + zap.Int("status_code", resp.StatusCode), + zap.String("raw_response", rawResponse), + ) + return fmt.Errorf("received non-success status code: %d, raw response: %s", resp.StatusCode, rawResponse) +} // HandleResponse processes an HTTP response for a Jamf API request. It handles different response types and errors accordingly. func (j *JamfAPIHandler) HandleResponse(resp *http.Response, out interface{}, log logger.Logger) error { diff --git a/httpclient/httpclient_api_handler.go b/httpclient/httpclient_api_handler.go index 072fa62..95fc0ea 100644 --- a/httpclient/httpclient_api_handler.go +++ b/httpclient/httpclient_api_handler.go @@ -16,7 +16,9 @@ type APIHandler interface { ConstructAPIAuthEndpoint(instanceName string, endpointPath string, log logger.Logger) string MarshalRequest(body interface{}, method string, endpoint string, log logger.Logger) ([]byte, error) MarshalMultipartRequest(fields map[string]string, files map[string]string, log logger.Logger) ([]byte, string, error) - HandleResponse(resp *http.Response, out interface{}, log logger.Logger) error + //HandleResponse(resp *http.Response, out interface{}, log logger.Logger) error + HandleAPISuccessResponse(resp *http.Response, out interface{}, log logger.Logger) error + HandleAPIErrorResponse(resp *http.Response, out interface{}, log logger.Logger) error GetContentTypeHeader(method string, log logger.Logger) string GetAcceptHeader() string GetDefaultBaseDomain() string diff --git a/httpclient/httpclient_request.go b/httpclient/httpclient_request.go index 0dce30c..87e23b7 100644 --- a/httpclient/httpclient_request.go +++ b/httpclient/httpclient_request.go @@ -350,22 +350,8 @@ func (c *Client) executeHTTPRequest(req *http.Request, log logger.Logger, method // // Returns: // - An error object parsed from the HTTP response, indicating the nature of the failure. -func (c *Client) handleErrorResponseV1(resp *http.Response, log logger.Logger, errorMessage, method, endpoint string) error { - apiErr := errors.HandleAPIError(resp, log) - - // Log the provided error message along with method, endpoint, and status code. - log.Error(errorMessage, - zap.String("method", method), - zap.String("endpoint", endpoint), - zap.Int("status_code", resp.StatusCode), - zap.String("error", apiErr.Error()), - ) - - return apiErr -} - func (c *Client) handleErrorResponse(resp *http.Response, out interface{}, log logger.Logger, method, endpoint string) error { - if err := c.APIHandler.HandleResponse(resp, out, log); err != nil { + if err := c.APIHandler.HandleAPIErrorResponse(resp, out, log); err != nil { log.Error("Failed to unmarshal HTTP response", zap.String("method", method), zap.String("endpoint", endpoint), @@ -395,7 +381,7 @@ func (c *Client) handleErrorResponse(resp *http.Response, out interface{}, log l // Returns: // - nil if the response was successfully unmarshalled into the 'out' parameter, or an error if unmarshalling failed. func (c *Client) handleSuccessResponse(resp *http.Response, out interface{}, log logger.Logger, method, endpoint string) error { - if err := c.APIHandler.HandleResponse(resp, out, log); err != nil { + if err := c.APIHandler.HandleAPISuccessResponse(resp, out, log); err != nil { log.Error("Failed to unmarshal HTTP response", zap.String("method", method), zap.String("endpoint", endpoint), From d92875acbbf73aed91c5e18273622f7db5216d7b Mon Sep 17 00:00:00 2001 From: ShocOne <62835948+ShocOne@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:06:43 +0000 Subject: [PATCH 2/2] Remove commented code in JamfAPIHandler --- apihandlers/jamfpro/jamfpro_api_response.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apihandlers/jamfpro/jamfpro_api_response.go b/apihandlers/jamfpro/jamfpro_api_response.go index 26c19e5..c3067a0 100644 --- a/apihandlers/jamfpro/jamfpro_api_response.go +++ b/apihandlers/jamfpro/jamfpro_api_response.go @@ -72,6 +72,7 @@ func (j *JamfAPIHandler) HandleAPIErrorResponse(resp *http.Response, out interfa return fmt.Errorf("received non-success status code: %d, raw response: %s", resp.StatusCode, rawResponse) } +/* // HandleResponse processes an HTTP response for a Jamf API request. It handles different response types and errors accordingly. func (j *JamfAPIHandler) HandleResponse(resp *http.Response, out interface{}, log logger.Logger) error { // Special handling for DELETE requests @@ -119,7 +120,7 @@ func (j *JamfAPIHandler) HandleResponse(resp *http.Response, out interface{}, lo // Unmarshal the response based on content type return j.unmarshalResponse(contentType, bodyBytes, out) } - +*/ // handleDeleteRequest handles the special case for DELETE requests, where a successful response might not contain a body. func (j *JamfAPIHandler) handleDeleteRequest(resp *http.Response) error { if resp.StatusCode >= 200 && resp.StatusCode < 300 {