I'm trying to send an Apple push notification from a Go appengine site. I'm using the apns2 library as follows:
cert, err := certificate.FromPemFile(pemFile, "")
if err != nil {
log.Fatalf("cert error: %v", err)
}
client := apns2.NewClient(cert).Development()
n := &apns2.Notification{...}
if res, err := client.Push(n); err != nil { ... }
On a local development server, it works fine; but in production I'm seeing:
Post https://api.development.push.apple.com/3/device/995aa87050518ca346f7254f3484d7d5c731ee93c35e3c359db9ddf95d035003:
dial tcp: lookup api.development.push.apple.com on [::1]:53: dial udp [::1]:53: socket: operation not permitted
It looks like appengine expects you to use its own urlfetch library when sending outbound requests, so I tried setting the underlying HTTPClient
to use that:
client.HTTPClient = urlfetch.Client(ctx)
However, the response from the Apple server is now
@@?HTTP/2 client preface string missing or corrupt. Hex dump for received bytes: 504f5354202f332f6465766963652f393935616138373035
I believe the problem is that Apple push notifications require HTTP/2, but urlfetch only implements HTTP/1.1.
How do I solve this problem? Is there a way for an appengine app to send an HTTP/2 request?
I dont know much about go appengine, but whatever it looks from the code, your client := apns2.NewClient(cert).Development()
line seems to be defective, i think for production, you dont need development cert, you need to have distribution cert. So check that is there any option available for it. Also, is certificates from apple's dev site are generated by you or by go appengine. If you have manually created that, then you have to create 2 types of certificates, one for developement and one for distribution/production, and when app is running in production mode, you need to use that certificates.
This would require going through the App Engine Sockets API. The documentation states:
Libraries that can accept a net.Conn should work without modification.
You can get a net.Conn
from the appengine/socket
package and pass it to a lib that will accept one, but in the case of apns2
it doesn't allow you to do this. However another user has submitted a pull request to the apns2
project that adds a distinct GAEClient
which can use App Engine sockets.
As of right now it looks like the commits still have not been pulled into the master branch, however you could still merge these updates manually into your own source tree as a workaround for now.