feat: Allow empty payloads

closes #40
This commit is contained in:
jr conlin 2017-02-11 21:50:18 -08:00 committed by jrconlin
parent 0d015c28b9
commit b2e621c798
5 changed files with 59 additions and 27 deletions

12
circle.yml Normal file
View File

@ -0,0 +1,12 @@
# circle ci file
machine:
post:
- pyenv global 2.7.13 3.5
dependencies:
pre:
- pip install -r test-requirements.txt
test:
override:
- nosetests -v pywebpush

View File

@ -152,7 +152,7 @@ class WebPusher:
'body': encrypted,
})
def send(self, data, headers=None, ttl=0, gcm_key=None, reg_id=None):
def send(self, data=None, headers=None, ttl=0, gcm_key=None, reg_id=None):
"""Encode and send the data to the Push Service.
:param data: A serialized block of data (see encode() ).
@ -169,22 +169,25 @@ class WebPusher:
# Encode the data.
if headers is None:
headers = dict()
encoded = self.encode(data)
# Append the p256dh to the end of any existing crypto-key
encoded = {}
headers = CaseInsensitiveDict(headers)
crypto_key = headers.get("crypto-key", "")
if crypto_key:
# due to some confusion by a push service provider, we should
# use ';' instead of ',' to append the headers.
# see https://github.com/webpush-wg/webpush-encryption/issues/6
crypto_key += ';'
crypto_key += "keyid=p256dh;dh=" + encoded["crypto_key"].decode('utf8')
headers.update({
'crypto-key': crypto_key,
'content-encoding': 'aesgcm',
'encryption': "keyid=p256dh;salt=" +
encoded['salt'].decode('utf8'),
})
if data:
encoded = self.encode(data)
# Append the p256dh to the end of any existing crypto-key
crypto_key = headers.get("crypto-key", "")
if crypto_key:
# due to some confusion by a push service provider, we should
# use ';' instead of ',' to append the headers.
# see https://github.com/webpush-wg/webpush-encryption/issues/6
crypto_key += ';'
crypto_key += (
"keyid=p256dh;dh=" + encoded["crypto_key"].decode('utf8'))
headers.update({
'crypto-key': crypto_key,
'content-encoding': 'aesgcm',
'encryption': "keyid=p256dh;salt=" +
encoded['salt'].decode('utf8'),
})
gcm_endpoint = 'https://android.googleapis.com/gcm/send'
if self.subscription_info['endpoint'].startswith(gcm_endpoint):
if not gcm_key:
@ -194,13 +197,14 @@ class WebPusher:
if not reg_id:
reg_id = self.subscription_info['endpoint'].rsplit('/', 1)[-1]
reg_ids.append(reg_id)
data = dict()
data['registration_ids'] = reg_ids
data['raw_data'] = base64.b64encode(
encoded.get('body')).decode('utf8')
data['time_to_live'] = int(
gcm_data = dict()
gcm_data['registration_ids'] = reg_ids
if data:
gcm_data['raw_data'] = base64.b64encode(
encoded.get('body')).decode('utf8')
gcm_data['time_to_live'] = int(
headers['ttl'] if 'ttl' in headers else ttl)
encoded_data = json.dumps(data)
encoded_data = json.dumps(gcm_data)
headers.update({
'Authorization': 'key='+gcm_key,
'Content-Type': 'application/json',

View File

@ -3,9 +3,9 @@ import json
import os
import unittest
import http_ece
from mock import patch
from nose.tools import eq_, ok_
import http_ece
import pyelliptic
from pywebpush import WebPusher, WebPushException, CaseInsensitiveDict
@ -83,11 +83,11 @@ class WebpushTestCase(unittest.TestCase):
push._repad(subscription_info['keys']['auth']))
decoded = http_ece.decrypt(
buffer=encoded['body'],
encoded['body'],
salt=raw_salt,
dh=raw_dh,
keyid=keyid,
authSecret=raw_auth
authSecret=raw_auth,
)
eq_(decoded.decode('utf8'), data)
@ -109,6 +109,22 @@ class WebpushTestCase(unittest.TestCase):
ok_('pre-existing' in ckey)
eq_(pheaders.get('content-encoding'), 'aesgcm')
@patch("requests.post")
def test_send_empty(self, mock_post):
recv_key = pyelliptic.ECC(curve="prime256v1")
subscription_info = self._gen_subscription_info(recv_key)
headers = {"Crypto-Key": "pre-existing",
"Authentication": "bearer vapid"}
data = None
WebPusher(subscription_info).send(data, headers)
eq_(subscription_info.get('endpoint'), mock_post.call_args[0][0])
pheaders = mock_post.call_args[1].get('headers')
eq_(pheaders.get('ttl'), '0')
ok_('encryption' not in pheaders)
eq_(pheaders.get('AUTHENTICATION'), headers.get('Authentication'))
ckey = pheaders.get('crypto-key')
ok_('pre-existing' in ckey)
@patch("requests.post")
def test_send_no_headers(self, mock_post):
recv_key = pyelliptic.ECC(curve="prime256v1")

View File

@ -1,4 +1,4 @@
http-ece==0.5.0
http-ece==0.7.0
python-jose>1.2.0
requests>2.11.0
flake8

View File

@ -3,7 +3,7 @@ import os
from setuptools import find_packages, setup
__version__ = "0.6.2"
__version__ = "0.6.3"
def read_from(file):