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

Commit 2d03c35

Browse files
authored
parse GOAWAY error responses from Apple (#71)
with latest x/net/http2.
1 parent 2f65712 commit 2d03c35

File tree

2 files changed

+19
-19
lines changed

2 files changed

+19
-19
lines changed

README.md

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -184,19 +184,6 @@ if e, ok := err.(*push.Error); ok {
184184
}
185185
```
186186

187-
##### GOAWAY errors
188-
189-
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:
190-
191-
> http2: server sent GOAWAY and closed the connection
192-
193-
You can run your application with HTTP/2 logging enabled to see the GOAWAY frames that were sent, including the reason.
194-
195-
```console
196-
$ GODEBUG=http2debug=1 ./myapp
197-
http2: Transport received GOAWAY len=46 LastStreamID=0 ErrCode=NO_ERROR Debug="{\"reason\":\"BadCertificateEnvironment\"}"
198-
```
199-
200187
### Website Push
201188

202189
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.

push/service.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import (
77
"crypto/tls"
88
"encoding/json"
99
"fmt"
10+
"io"
1011
"net/http"
12+
"strings"
1113
"time"
1214

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

74-
resp, err := s.Client.Do(req)
76+
tr := s.Client.Transport
77+
if tr == nil {
78+
tr = http.DefaultTransport
79+
}
80+
resp, err := tr.RoundTrip(req)
7581
if err != nil {
82+
if e, ok := err.(http2.GoAwayError); ok {
83+
// parse DebugData as JSON. no status code known (0)
84+
return "", parseErrorResponse(strings.NewReader(e.DebugData), 0)
85+
}
7686
return "", err
7787
}
7888
defer resp.Body.Close()
@@ -81,26 +91,29 @@ func (s *Service) Push(deviceToken string, headers *Headers, payload []byte) (st
8191
return resp.Header.Get("apns-id"), nil
8292
}
8393

94+
return "", parseErrorResponse(resp.Body, resp.StatusCode)
95+
}
96+
97+
func parseErrorResponse(body io.Reader, statusCode int) error {
8498
var response struct {
8599
// Reason for failure
86100
Reason string `json:"reason"`
87101
// Timestamp for 410 StatusGone (ErrUnregistered)
88102
Timestamp int64 `json:"timestamp"`
89103
}
90-
err = json.NewDecoder(resp.Body).Decode(&response)
104+
err := json.NewDecoder(body).Decode(&response)
91105
if err != nil {
92-
return "", err
106+
return err
93107
}
94108

95109
es := &Error{
96110
Reason: mapErrorReason(response.Reason),
97-
Status: resp.StatusCode,
111+
Status: statusCode,
98112
}
99113

100114
if response.Timestamp != 0 {
101115
// the response.Timestamp is Milliseconds, but time.Unix() requires seconds
102116
es.Timestamp = time.Unix(response.Timestamp/1000, 0).UTC()
103117
}
104-
105-
return "", es
118+
return es
106119
}

0 commit comments

Comments
 (0)