专栏名称: 编程派
Python程序员都在看的公众号,跟着编程派一起学习Python,看最新国外教程和资源!
目录
相关文章推荐
Python爱好者社区  ·  应届生炒到66.8w年薪,真心建议冲冲这个新 ... ·  5 天前  
Python中文社区  ·  狂暴大牛市该买点啥?用量化选股抓住机会 ·  6 天前  
Python开发者  ·  开源 9 年后,词频数据库 ... ·  1 周前  
Python爱好者社区  ·  1885页的Python完整版电子书 ·  1 周前  
Python爱好者社区  ·  yyds!Kaggle教程 ·  1 周前  
51好读  ›  专栏  ›  编程派

实战 | Python使用HTTP2实现苹果原生推送

编程派  · 公众号  · Python  · 2017-02-20 11:29

正文

本文约 4405 字,读完可能需要 6 分钟。

作者:风中纸鸢

原文:http://52sox.com/python-use-http2-for-apns

说起苹果的推送,可能很多开发人员就开始头疼了,因为实现苹果推送服务是1个比较蛋疼的事情,于是便引入了第3方推送平台,比如极光、信鸽之类的服务。

由于苹果原生 APNs 蛋疼的协议,致使本来很简单的1个推送服务让人望而却步。直到苹果最近的 HTTP 2协议的出现才有所改善。

一直以来, http 2这样新潮的名字都只能出现在 nodejs 、 go 这样的编程语言中。在网上输入关键字 http 2,点击进去就会发现各种各样使用 nodejs 实现的 HTTP 2服务器,利用 nginx 版本1.9.5版本搭建 HTTP 2 服务之类的文章。这些文章确实让人热血沸腾、激动人心。

然而,在 Python 中迟迟不见有任何的实现,不免觉得已经落伍了。实际上,在项目过程中更多追求的是稳定和健壮,更多关于新潮的技术只能先看看。比如最近比较火的直播节目,实际上用 Python 也是可以完全实现的,而且性能还是挺不错的。

下面是一些编程语言使用 HTTP 2的原生推送的实现:

  • node-apn,1个基于nodejs语言的实现。

  • apns-http2,1个基于Java语言的实现

  • apns2,1个基于Go语言的实现

而在 Python 中,还完全停留在旧的 Binary API的版本中,而唯一的1个HTTP 2的实现PyAPNs2在Python2中不能正常的运行。不过,不要灰心,下面我们自己动手写1个。

在这里,我们简单的通过 Python 来实现以下内容:

  • 原生 APNs 推送

  • 推送的异常处理

下面我们分别来进行说明。

文档说明

首先来看下官方的文档,如果你直接从百度上进行搜索然后进行点击后会发现对应的链接跳转是1个404页面,关于这个问题已经在苹果APNs推送页面丢失问题中进行说明了,其跳转后的地址如下:

  1. https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html

而实际对应页面的地址应该如下所示:

  1. https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html

由于苹果官方采用了 HTTP 2协议,相比之前的 Binary API 而言,可以说简化了很多内容,自然而言代码也精简了很多。

依赖的库

为了实现 HTTP 2的推送服务,我们需要安装 hyper 这个库,它是1个 Python 实现的 HTTP 2的客户端,我们可以通过 pip 进行安装。

而该库主要依赖于 cryptography 、 pyOpenSSL 这2个库,因此我们需要提前安装好 cython 和 openssl 的 C 库开发文件。

  1. pip install hyper

实际代码

安装完成 hyper 后,我们可以通过如下的方式来实现1个推送服务:

  1. from hyper import HTTPConnection, tls

  2. token = 'xxxxxx-xxxxx-xxxx-xxxxx'

  3. payload = {

  4.    'aps': {

  5.        'alert': '测试推送',

  6.        'sound': 'default',

  7.        'badge': 1,

  8.    }

  9. }

  10. headers = {

  11.    "apns-topic": '证书的主题名称',

  12. }

  13. conn = HTTPConnection('api.development.push.apple.com:443',

  14.                      ssl_context=tls.init_context(cert='证书文件名称'))

  15. conn.request('POST', '/3/device/%s' %

  16.             token, body=json.dumps(payload), headers=headers)

  17. resp = conn.get_response()

  18. d = resp.read()

可以看到,这个推送服务的核心代码只有寥寥3行就已经完成了。在这里,我们通过 HTTPConnection 连接到苹果推送服务器的443端口上,然后我们初始化推送证书。

之后我们通过 POST 方法请求苹果的推送服务器,在这里需要传递要推送的设备的 Token ,然后推送的内容为1个 JSON 的格式,最后再附对应的头信息即可。

如果推送失败后,苹果的推送服务器会返回1个错误的信息。下面是1个 HTTP 2推送成功后的截图:

而后是 Binary API 推送的接口的截图:

可以看到,我们成功的接收到了推送的消息。相比旧的 Binary API 接口, HTTP 2的推送服务的速度快2倍以上,在测试的时候,基本上在5 s 内就可以收到,而旧的接口基本上等待15-30 s 才可以收到。

而在 HTTP 2协议中,主要有以下一些响应的状态码:

  • 200,推送成功。

  • 400,请求有问题。

  • 403,证书或 Token 有问题。

  • 405,请求方式不正确,只支持 POST 请求

  • 410,设备的 Token 与证书不一致

更多状态码可以查阅

开源的实现

上述推送服务虽然简单,但是操作起来还是挺繁琐了,特别是错误处理这块。在这里,要感谢我隔壁哥们的辛勤付出,他对上述的代码进行了封装并进行了开源。

我们可以通过 pip 直接进行安装:

  1. pip install applepush

然后我们只需要在代码中进行如下的调用即可:

  1. from applepush import ApplePush

  2. apns = ApplePush('证书文件名称', 'bundle ID')

  3. resp = apns.single_push('苹果设备token', "推送内容")

而返回的结果类似如下:

  1. {

  2.    'status': 成功为200,错误为其它,

  3.    'headers': {

  4.        'apns-id': 苹果推送返回的UUID,

  5.    },

  6.    'data': 苹果接口返回的字符串,

  7.    'error_msg': 错误原因,如果推送成功为None

  8. }

然后我们根据返回的结果与实际业务进行结合。

结语

虽然通过 Python 使用 HTTP 2来实现苹果的推送服务是1个比较简单的事情,甚至会觉得比较枯燥无味的事情。 但是,如果你从 Binary API到HTTP2,把这2个协议研究一遍,再把证书的签名及转换的内容过一遍,可以查看另1篇文章使用openssl实现私钥和证书的转换,或许你会收获更多。

当然,在这个过程中还有其他一些内容,比如根据证书内容来自动实现识别推送环境(测试还是生产),进而不同的推送版本,以及如何嵌入 C 库来实现更快的 HTTP 2推送服务都是可以实现的。

参考文章:

https://imququ.com/post/nginx-http2-patch.html 

http://hyper.readthedocs.io/en/latest/


题图:pexels,CC0 授权。

点击阅读原文,查看更多 Python 教程和资源。