Skip to content
This repository has been archived by the owner on Jun 6, 2023. It is now read-only.

Commit

Permalink
parse GOAWAY error responses from Apple (#71)
Browse files Browse the repository at this point in the history
with latest x/net/http2.
  • Loading branch information
nathany authored Jun 29, 2016
1 parent 2f65712 commit 2d03c35
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 19 deletions.
13 changes: 0 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,19 +184,6 @@ if e, ok := err.(*push.Error); ok {
}
```

##### GOAWAY errors

You will never receive some of Apple's documented error responses, such as `BadCertificateEnvironment`. This is because Apple sometimes returns error messages in a GOAWAY frame while disconnecting rather than in the usual DATA frame. Go [doesn't currently](https://github.com/golang/go/issues/14627) extract these GOAWAY errors. Instead you may see an error like this:

> http2: server sent GOAWAY and closed the connection
You can run your application with HTTP/2 logging enabled to see the GOAWAY frames that were sent, including the reason.

```console
$ GODEBUG=http2debug=1 ./myapp
http2: Transport received GOAWAY len=46 LastStreamID=0 ErrCode=NO_ERROR Debug="{\"reason\":\"BadCertificateEnvironment\"}"
```

### Website Push

Before you can send push notifications through Safari and the Notification Center, you must provide a push package, which is a signed zip file containing some JSON and icons.
Expand Down
25 changes: 19 additions & 6 deletions push/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"

"golang.org/x/net/http2"
Expand Down Expand Up @@ -71,8 +73,16 @@ func (s *Service) Push(deviceToken string, headers *Headers, payload []byte) (st
req.Header.Set("Content-Type", "application/json")
headers.set(req.Header)

resp, err := s.Client.Do(req)

This comment has been minimized.

Copy link
@leopay

leopay Jul 4, 2016

@nathany Are there some other reason not using net.http.Client.Do. After this modify, set net.http.client.Timeout will be no longer work.

This comment has been minimized.

Copy link
@nathany

nathany Jul 4, 2016

Author Contributor

@leopay Yah. GoAwayError gets amended by Client.Do so I can't pull out the DebugData.

Let's continue this discussion in #72 and figure out how to get it working again.

tr := s.Client.Transport
if tr == nil {
tr = http.DefaultTransport
}
resp, err := tr.RoundTrip(req)
if err != nil {
if e, ok := err.(http2.GoAwayError); ok {
// parse DebugData as JSON. no status code known (0)
return "", parseErrorResponse(strings.NewReader(e.DebugData), 0)
}
return "", err
}
defer resp.Body.Close()
Expand All @@ -81,26 +91,29 @@ func (s *Service) Push(deviceToken string, headers *Headers, payload []byte) (st
return resp.Header.Get("apns-id"), nil
}

return "", parseErrorResponse(resp.Body, resp.StatusCode)
}

func parseErrorResponse(body io.Reader, statusCode int) error {
var response struct {
// Reason for failure
Reason string `json:"reason"`
// Timestamp for 410 StatusGone (ErrUnregistered)
Timestamp int64 `json:"timestamp"`
}
err = json.NewDecoder(resp.Body).Decode(&response)
err := json.NewDecoder(body).Decode(&response)
if err != nil {
return "", err
return err
}

es := &Error{
Reason: mapErrorReason(response.Reason),
Status: resp.StatusCode,
Status: statusCode,
}

if response.Timestamp != 0 {
// the response.Timestamp is Milliseconds, but time.Unix() requires seconds
es.Timestamp = time.Unix(response.Timestamp/1000, 0).UTC()
}

return "", es
return es
}

0 comments on commit 2d03c35

Please sign in to comment.