Skip to content

Commit 8db2297

Browse files
committed
Add and delete files related to Jamf Pro API handlers
1 parent c15107e commit 8db2297

File tree

7 files changed

+388
-509
lines changed

7 files changed

+388
-509
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// graph_api_error_messages.go
2+
package graph
3+
4+
import (
5+
"bytes"
6+
"encoding/json"
7+
"io"
8+
"net/http"
9+
"strings"
10+
11+
"github.com/PuerkitoBio/goquery"
12+
)
13+
14+
// APIHandlerError represents an error response from the Jamf Pro API.
15+
type APIHandlerError struct {
16+
HTTPStatusCode int `json:"httpStatusCode"`
17+
ErrorType string `json:"errorType"`
18+
ErrorMessage string `json:"errorMessage"`
19+
ExtraDetails map[string]interface{} `json:"extraDetails"`
20+
}
21+
22+
// ReturnAPIErrorResponse parses an HTTP error response from the Jamf Pro API.
23+
func (g *GraphAPIHandler) ReturnAPIErrorResponse(resp *http.Response) *APIHandlerError {
24+
var errorMessage, errorType string
25+
var extraDetails map[string]interface{}
26+
27+
// Safely read the response body
28+
bodyBytes, readErr := io.ReadAll(resp.Body)
29+
if readErr != nil {
30+
return &APIHandlerError{
31+
HTTPStatusCode: resp.StatusCode,
32+
ErrorType: "ReadError",
33+
ErrorMessage: "Failed to read response body",
34+
}
35+
}
36+
37+
// Ensure the body can be re-read for subsequent operations
38+
resp.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
39+
40+
contentType := resp.Header.Get("Content-Type")
41+
42+
// Handle JSON content type
43+
if strings.Contains(contentType, "application/json") {
44+
description, parseErr := ParseJSONErrorResponse(bodyBytes)
45+
if parseErr == nil {
46+
errorMessage = description
47+
errorType = "JSONError"
48+
} else {
49+
errorMessage = "Failed to parse JSON error response: " + parseErr.Error()
50+
}
51+
} else if strings.Contains(contentType, "text/html") {
52+
// Handle HTML content type
53+
bodyBytes, err := io.ReadAll(resp.Body)
54+
if err == nil {
55+
errorMessage = ExtractErrorMessageFromHTML(string(bodyBytes))
56+
errorType = "HTMLError"
57+
} else {
58+
errorMessage = "Failed to read response body for HTML error parsing"
59+
}
60+
} else {
61+
// Fallback for unhandled content types
62+
errorMessage = "An unknown error occurred"
63+
}
64+
65+
return &APIHandlerError{
66+
HTTPStatusCode: resp.StatusCode,
67+
ErrorType: errorType,
68+
ErrorMessage: errorMessage,
69+
ExtraDetails: extraDetails,
70+
}
71+
}
72+
73+
// ExtractErrorMessageFromHTML attempts to parse an HTML error page and extract a combined human-readable error message.
74+
func ExtractErrorMessageFromHTML(htmlContent string) string {
75+
r := bytes.NewReader([]byte(htmlContent))
76+
doc, err := goquery.NewDocumentFromReader(r)
77+
if err != nil {
78+
return "Unable to parse HTML content"
79+
}
80+
81+
var messages []string
82+
doc.Find("p").Each(func(i int, s *goquery.Selection) {
83+
text := strings.TrimSpace(s.Text())
84+
if text != "" {
85+
messages = append(messages, text)
86+
}
87+
})
88+
89+
combinedMessage := strings.Join(messages, " - ")
90+
return combinedMessage
91+
}
92+
93+
// ParseJSONErrorResponse parses the JSON error message from the response body.
94+
func ParseJSONErrorResponse(body []byte) (string, error) {
95+
var errorResponse struct {
96+
HTTPStatus int `json:"httpStatus"`
97+
Errors []struct {
98+
Code string `json:"code"`
99+
Description string `json:"description"`
100+
ID string `json:"id"`
101+
Field string `json:"field"`
102+
} `json:"errors"`
103+
}
104+
105+
err := json.Unmarshal(body, &errorResponse)
106+
if err != nil {
107+
return "", err
108+
}
109+
110+
if len(errorResponse.Errors) > 0 {
111+
return errorResponse.Errors[0].Description, nil
112+
}
113+
114+
return "No error description available", nil
115+
}

0 commit comments

Comments
 (0)