Repository: PagerDuty/go-pagerduty
Pull request #452 (2022-07-29 18:50:33)

Fix ResponderRequest regression
This provides a fix for issue #451 where _ResponderRequest_ has been broken (requests are returned a 2100 _Not Found_). 

The PR also omits `incident_responders` from the request when empty, as it's not required/useful.

I fixed the related test in `incident_test.go` and tested successfully both with that test and my own test which actually sent the successful POSTs to the `/incidents/{id}/responder_requests` endpoint.


Patch:
diff --git a/client.go b/client.go
index 867af70..3ab9382 100644
--- a/client.go
+++ b/client.go
@@ -590,8 +590,6 @@ func (c *Client) checkResponse(resp *http.Response, err error) (*http.Response,
 func (c *Client) getErrorFromResponse(resp *http.Response) APIError {
 	// check whether the error response is declared as JSON
 	if !strings.HasPrefix(resp.Header.Get("Content-Type"), "application/json") {
-		defer resp.Body.Close()
-
 		aerr := APIError{
 			StatusCode: resp.StatusCode,
 			message:    fmt.Sprintf("HTTP response with status code %d does not contain Content-Type: application/json", resp.StatusCode),
diff --git a/incident.go b/incident.go
index ae5c1b2..8810a0c 100644
--- a/incident.go
+++ b/incident.go
@@ -657,7 +657,12 @@ type ResponderRequestResponse struct {
 // ResponderRequestTarget specifies an individual target for the responder request.
 type ResponderRequestTarget struct {
 	APIObject
-	Responders IncidentResponders `json:"incident_responders"`
+	Responders IncidentResponders `json:"incident_responders,omitempty"`
+}
+
+// ResponderRequestTargetWrapper is a wrapper for a ResponderRequestTarget.
+type ResponderRequestTargetWrapper struct {
+	Target ResponderRequestTarget `json:"responder_request_target"`
 }
 
 // ResponderRequestOptions defines the input options for the Create Responder function.
@@ -665,7 +670,7 @@ type ResponderRequestOptions struct {
 	From        string                   `json:"-"`
 	Message     string                   `json:"message"`
 	RequesterID string                   `json:"requester_id"`
-	Targets     []ResponderRequestTarget `json:"responder_request_targets"`
+	Targets     []ResponderRequestTargetWrapper `json:"responder_request_targets"`
 }
 
 // ResponderRequest contains the API structure for an incident responder request.
@@ -674,7 +679,7 @@ type ResponderRequest struct {
 	Requester   User                     `json:"requester,omitempty"`
 	RequestedAt string                   `json:"request_at,omitempty"`
 	Message     string                   `json:"message,omitempty"`
-	Targets     []ResponderRequestTarget `json:"responder_request_targets"`
+	Targets     []ResponderRequestTargetWrapper `json:"responder_request_targets"`
 }
 
 // ResponderRequest will submit a request to have a responder join an incident.


Test patch:
diff --git a/incident_test.go b/incident_test.go
index 208dcbf..9a043aa 100644
--- a/incident_test.go
+++ b/incident_test.go
@@ -808,12 +808,14 @@ func TestIncident_ResponderRequest(t *testing.T) {
 		},
 		"message": "Help",
 		"responder_request_targets": [{
-			"id": "PJ25ZYX",
-			"type": "user_reference",
-			"incident_responders": {
-				"state": "pending",
-				"user": {
-					"id": "PJ25ZYX"
+			"responder_request_target": {
+				"id": "PJ25ZYX",
+				"type": "user_reference",
+				"incident_responders": {
+					"state": "pending",
+					"user": {
+						"id": "PJ25ZYX"
+					}
 				}
 			}
 		}]
@@ -823,37 +825,39 @@ func TestIncident_ResponderRequest(t *testing.T) {
 	client := defaultTestClient(server.URL, "foo")
 	from := "foo@bar.com"
 
-	r := ResponderRequestTarget{}
-	r.ID = "PJ25ZYX"
-	r.Type = "user_reference"
+	request_target := ResponderRequestTarget{}
+	request_target.ID = "PJ25ZYX"
+	request_target.Type = "user_reference"
 
-	targets := []ResponderRequestTarget{r}
+	request_target_wrapper := ResponderRequestTargetWrapper{Target: request_target}
+	request_targets := []ResponderRequestTargetWrapper{request_target_wrapper}
 
 	input := ResponderRequestOptions{
 		From:        from,
-		Message:     "help",
+		Message:     "Help",
 		RequesterID: "PL1JMK5",
-		Targets:     targets,
+		Targets:     request_targets,
 	}
 
 	user := User{}
 	user.ID = "PL1JMK5"
 	user.Type = "user_reference"
 
-	target := ResponderRequestTarget{}
-	target.ID = "PJ25ZYX"
-	target.Type = "user_reference"
-	target.Responders.State = "pending"
-	target.Responders.User.ID = "PJ25ZYX"
+	want_target := ResponderRequestTarget{}
+	want_target.ID = "PJ25ZYX"
+	want_target.Type = "user_reference"
+	want_target.Responders.State = "pending"
+	want_target.Responders.User.ID = "PJ25ZYX"
 
-	targets = []ResponderRequestTarget{target}
+	want_target_wrapper := ResponderRequestTargetWrapper{Target: want_target}
+	want_targets := []ResponderRequestTargetWrapper{want_target_wrapper}
 
 	want := &ResponderRequestResponse{
 		ResponderRequest: ResponderRequest{
 			Incident:  Incident{},
 			Requester: user,
 			Message:   "Help",
-			Targets:   targets,
+			Targets:   want_targets,
 		},
 	}
 	res, err := client.ResponderRequest(id, input)