Отправить Apple push-уведомление с сайта Go appengine

Я пытаюсь отправить уведомление Apple с сайта Go appengine. Я использую apns2 library следующим образом:

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 { ... }

На локальном сервере разработки он работает нормально; но в производстве я вижу:

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

Похоже, appengine ожидает, что вы будете использовать свою собственную библиотеку urlfetch при отправке исходящих запросов, поэтому я попытался установить базовый HTTPClient для использования что:

client.HTTPClient = urlfetch.Client(ctx)

Однако ответ от сервера Apple теперь

@@?HTTP/2 client preface string missing or corrupt. Hex dump for received bytes: 504f5354202f332f6465766963652f393935616138373035

Я считаю, что проблема заключается в том, что Apple push notifications требует HTTP/2, но urlfetch реализует только HTTP/1.1.

Как решить эту проблему? Есть ли способ приложения appengine для отправки запроса HTTP/2?

Ответы

Ответ 1

Для этого потребуется пройти через API-интерфейсы App Engine Sockets. В документации указано:

Библиотеки, которые могут принимать net.Conn, должны работать без изменений.

Вы можете получить net.Conn из пакета appengine/socket и передать его в lib, который его примет, но в случае apns2 он не позволит вам это сделать. Однако другой пользователь отправил запрос на перенос в проект apns2, который добавляет отдельный GAEClient, который может использовать сокеты App Engine.

Как сейчас, похоже, что коммиты все еще не были втянуты в главную ветвь, однако вы все равно можете объединить эти обновления вручную в свое исходное дерево в качестве обходного пути.

Ответ 2

Я не знаю много о том, как go appengine, но что бы он ни смотрел с кода, ваша строка client := apns2.NewClient(cert).Development() кажется дефектной, я думаю, что для производства вам не нужен сертификат разработки, вам нужно иметь сертификат распространения. Поэтому проверьте, есть ли у него какой-либо вариант. Кроме того, вы получаете сертификаты от веб-сайта Apple Dev или отправляете appengine. Если вы создали вручную это, вам нужно создать два типа сертификатов: один для разработки и один для распространения/производства, а когда приложение работает в рабочем режиме, вам необходимо использовать эти сертификаты.