Skip to content
Snippets Groups Projects
Commit fa76c4b1 authored by Phillip Harris's avatar Phillip Harris
Browse files

Merge branch 'status-code-fix' into 'master'

Status code fix

See merge request !1
parents cf56b18a 6dc80627
Branches
Tags v1.0.9
1 merge request!1Status code fix
......@@ -8,6 +8,7 @@ import (
"strings"
"github.com/go-resty/resty/v2"
"github.com/k0kubun/pp"
)
type (
......@@ -43,7 +44,7 @@ func (e ExpoClient) IsPushToken(token string) bool {
}
//Publish sends push messages in chunks of a given size, default MaxMessages
func (e ExpoClient) Publish(message PushMessage, nums ...int) (response PushResponse, err error) {
func (e ExpoClient) Publish(message PushMessage, nums ...int) (returnResponse PushResponse, err error) {
//default to MaxMessages
numToSend := MaxMessages
//if there are more than one nums, use the first one to set the numToSend
......@@ -70,7 +71,7 @@ func (e ExpoClient) Publish(message PushMessage, nums ...int) (response PushResp
//range over the chunks
for _, chunk := range chunks {
// build the push response
r := PushResponse{}
chunkResponse := PushResponse{}
//set the message.To list to this current chunk
message.To = chunk
//build the request
......@@ -80,102 +81,151 @@ func (e ExpoClient) Publish(message PushMessage, nums ...int) (response PushResp
SetHeader("Accept", "application/json").
SetAuthToken(e.token).
SetBody(message).
SetResult(&r)
SetResult(&chunkResponse)
//make the response
var resp *resty.Response
var restResponse *resty.Response
//make the request
resp, err = req.Post(url)
//check for errors
restResponse, err = req.Post(url)
//check for network or similar errors
if err != nil {
log.Printf("Failed - unable to marshall body: %d\n", restResponse.StatusCode())
log.Printf("Outgoing: %v", message)
log.Printf("Response: %v", string(restResponse.Body()))
//add each token from the chunk into individual error records
for _, token := range chunk {
response.Data = append(response.Data, PushResponseData{
returnResponse.Data = append(returnResponse.Data, PushResponseData{
Status: "error",
Token: token,
Message: "Network failure while sending message to " + token,
Message: "Failure while sending message to " + token,
Details: PushResponseDataDetails{
"error": NetworkFailure,
"message": err.Error(),
"body": string(restResponse.Body()[:200]),
},
},
)
}
//go to next chunk, skipping past other processing
continue
} else {
if resp.StatusCode() < http.StatusOK || resp.StatusCode() >= 299 {
err = json.Unmarshal(resp.Body(), &r)
if err != nil {
return
}
}
// err==nil, so we check len(r.Errors)
if len(r.Errors) > 0 {
for _, error := range r.Errors {
switch error.Code {
case "PUSH_TOO_MANY_EXPERIENCE_IDS":
// now we take the detail string and unmarshal it into a map
var details map[string][]string
err := json.Unmarshal(error.Details, &details)
if err != nil {
// throw error about unmarshaling
log.Println(err)
continue
}
for id, list := range details {
// at this point we have the message details
for _, token := range chunk {
if sliceContains(list, token) {
det := PushResponseDataDetails{
"error": TooManyExperiences,
"experience-id": id,
}
prd := PushResponseData{}
prd.Status = "error"
prd.Token = token
prd.Message = fmt.Sprintf("Server returned mixed experiences error while sending message to %s", token)
prd.Details = PushResponseDataDetails{}
prd.Details["error"] = det["error"].(string)
prd.Details["experience-id"] = det["experience-id"].(string)
response.Data = append(response.Data, prd)
}
}
}
default:
}
}
continue
}
}
// http status is not OK
if resp.StatusCode() != http.StatusOK {
if len(response.Errors) > 0 {
//network request succeeded and got a response
//if status not ok, check the chunk for a marshalable error content.
//if not, report as error and add all records into return response
if restResponse.StatusCode() != http.StatusOK {
err = json.Unmarshal(restResponse.Body(), &chunkResponse)
if err != nil {
log.Printf("Failed - unable to marshall body: %d\n", restResponse.StatusCode())
log.Printf("Outgoing: %v", message)
log.Printf("Response: %v", string(restResponse.Body()))
//add error records to the resultResponse for the users in this chunk
for _, token := range chunk {
response.Data = append(response.Data, PushResponseData{
returnResponse.Data = append(returnResponse.Data, PushResponseData{
Status: "error",
Token: token,
Message: fmt.Sprintf("Server returned %d while sending message to %s", resp.StatusCode(), token),
Message: fmt.Sprintf("Server returned %d while sending message to %s", restResponse.StatusCode(), token),
Details: PushResponseDataDetails{
"error": "ServerFailure",
"response-error": r.Errors,
"http-status": resp.StatusCode(),
"error": StatusCodeFail,
"response-error": chunkResponse.Errors,
"http-status": restResponse.StatusCode(),
"body": string(restResponse.Body()[:200]),
},
},
)
}
response.Errors = append(response.Errors, r.Errors...)
continue
}
continue
}
// check for specific, returned errors
if len(chunkResponse.Errors) > 0 {
for _, error := range chunkResponse.Errors {
switch error.Code {
//error = tokens are from mixed experiences
case TooManyExperiences:
// now we take the detail string and unmarshal it into a map
var details map[string][]string
err := json.Unmarshal(error.Details, &details)
if err != nil {
//detail string was unmarshalable, include entire token set in return and log errors
log.Println(err)
log.Printf("Outgoing: %v", message)
log.Printf("Response: %v", string(restResponse.Body()))
for _, token := range chunk {
returnResponse.Data = append(returnResponse.Data, PushResponseData{
Status: "error",
Token: token,
Message: fmt.Sprintf("Server returned unmarshalable content with mixed experiences error while sending message to %s", token),
Details: PushResponseDataDetails{
"error": TooManyExperiences,
"response-error": chunkResponse.Errors,
"http-status": restResponse.StatusCode(),
"body": string(restResponse.Body()[:200]),
},
},
)
}
continue //move to the next error in this chunk
}
//details were unmarshalled. in mixed experiences a details field is included that maps the experience against the token.
for id, list := range details {
//for each token, attempt to retrieve the details and add to return response
for _, token := range chunk {
//if the token from the chunk matches the token from the details list it means that this token was from a mixed experience
if sliceContains(list, token) {
det := PushResponseDataDetails{
"error": TooManyExperiences,
"experience-id": id,
}
prd := PushResponseData{}
prd.Status = "error"
prd.Token = token
prd.Message = fmt.Sprintf("Server returned mixed experiences error while sending message to %s", token)
prd.Details = PushResponseDataDetails{}
prd.Details["error"] = det["error"].(string)
prd.Details["experience-id"] = det["experience-id"].(string)
returnResponse.Data = append(returnResponse.Data, prd)
}
}
}
//expo allows only 100 at a time (as at 17.09.21). Should not fail unless we changed the amount sending or expo has changed the amount allowed.
case TooManyNotifications:
log.Printf("Too many notifications were sent:%d", numToSend)
//this should never happen, all current codes listed on expo page
//https://docs.expo.dev/push-notifications/sending-notifications/
//are currently accounted for. If it occurs, log the details and investigate what new error has occured.
default:
errorString := pp.Sprint(error)
log.Print(errorString)
for _, token := range chunk {
returnResponse.Data = append(returnResponse.Data, PushResponseData{
Status: "error",
Token: token,
Message: fmt.Sprintf("Server returned unexpected error to %s", token),
Details: PushResponseDataDetails{
"error": UnexpectedError,
"response-error": chunkResponse.Errors,
"http-status": restResponse.StatusCode(),
"body": string(restResponse.Body()[:200]),
},
},
)
}
}
}
continue //move to next chunk since there was a total send failure
}
//add the tokens into the overall response
for i := range r.Data {
r.Data[i].Token = chunk[i]
for i := range chunkResponse.Data {
chunkResponse.Data[i].Token = chunk[i]
}
// add the returned data into the overall response
response.Data = append(response.Data, r.Data...)
returnResponse.Data = append(returnResponse.Data, chunkResponse.Data...)
//add any errors to the response, though should not happen as errors are processed above
returnResponse.Errors = append(returnResponse.Errors, chunkResponse.Errors...)
}
return response, nil
return returnResponse, nil
}
func (e ExpoClient) GetReceipts(ids []string, nums ...int) (receipt PushReceiptResponse, err error) {
......
......@@ -9,6 +9,9 @@ const (
MaxReceipts = 1000
// error strings
TooManyExperiences = "PUSH_TOO_MANY_EXPERIENCE_IDS"
NetworkFailure = "NetworkFailure"
TooManyExperiences = "PUSH_TOO_MANY_EXPERIENCE_IDS"
NetworkFailure = "NetworkFailure"
StatusCodeFail = "StatusNotOK"
TooManyNotifications = "PUSH_TOO_MANY_NOTIFICATIONS"
UnexpectedError = "UnexpectedError"
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment