Merge pull request #11 from jrconlin/bug/10

bug: make header keys case insenstive
This commit is contained in:
JR Conlin 2016-05-17 16:23:33 -07:00
commit 4464fb972d
4 changed files with 46 additions and 7 deletions

View File

@ -1,3 +1,6 @@
## 0.3.4 (2016-05-17)
bug: make header keys case insenstive
## 0.3.3 (2016-05-17)
bug: force key string encoding to utf8

View File

@ -14,6 +14,33 @@ class WebPushException(Exception):
pass
class CaseInsensitiveDict(dict):
"""A dictionary that has case-insensitive keys"""
def __init__(self, data={}, **kwargs):
for key in data:
dict.__setitem__(self, key.lower(), data[key])
self.update(kwargs)
def __contains__(self, key):
return dict.__contains__(self, key.lower())
def __setitem__(self, key, value):
dict.__setitem__(self, key.lower(), value)
def __getitem__(self, key):
return dict.__getitem__(self, key.lower())
def __delitem__(self, key):
dict.__delitem__(self, key.lower())
def get(self, key, default=None):
try:
return self.__getitem__(key)
except KeyError:
return default
class WebPusher:
"""WebPusher encrypts a data block using HTTP Encrypted Content Encoding
for WebPush.
@ -109,12 +136,12 @@ class WebPusher:
dh=self.receiver_key,
authSecret=self.auth_key)
return {
return CaseInsensitiveDict({
'crypto_key': base64.urlsafe_b64encode(
server_key.get_pubkey()).strip('='),
'salt': base64.urlsafe_b64encode(salt).strip("="),
'body': encrypted,
}
})
def send(self, data, headers={}, ttl=0):
"""Encode and send the data to the Push Service.
@ -129,6 +156,7 @@ class WebPusher:
# Encode the data.
encoded = self.encode(data)
# Append the p256dh to the end of any existing crypto-key
headers = CaseInsensitiveDict(headers)
crypto_key = headers.get("crypto-key", "")
if crypto_key:
crypto_key += ','

View File

@ -7,7 +7,7 @@ from mock import patch
from nose.tools import eq_, ok_
import pyelliptic
from pywebpush import WebPusher, WebPushException
from pywebpush import WebPusher, WebPushException, CaseInsensitiveDict
class WebpushTestCase(unittest.TestCase):
@ -94,15 +94,23 @@ class WebpushTestCase(unittest.TestCase):
def test_send(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"}
headers = {"Crypto-Key": "pre-existing",
"Authentication": "bearer vapid"}
data = "Mary had a little lamb"
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' in pheaders)
eq_(pheaders.get('authentication'), headers.get('authentication'))
eq_(pheaders.get('AUTHENTICATION'), headers.get('Authentication'))
ckey = pheaders.get('crypto-key')
ok_('pre-existing,' in ckey)
eq_(pheaders.get('content-encoding'), 'aesgcm')
def test_ci_dict(self):
ci = CaseInsensitiveDict({"Foo": "apple", "bar": "banana"})
eq_('apple', ci["foo"])
eq_('apple', ci.get("FOO"))
eq_('apple', ci.get("Foo"))
del (ci['FOO'])
eq_(None, ci.get('Foo'))

View File

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