29ddda4508
As of January 1 2019, Mozilla requires that all GitHub projects include this CODE_OF_CONDUCT.md file in the project root. The file has two parts: Required Text - All text under the headings Community Participation Guidelines and How to Report, are required, and should not be altered. Optional Text - The Project Specific Etiquette heading provides a space to speak more specifically about ways people can work effectively and inclusively together. Some examples of those can be found on the Firefox Debugger project, and Common Voice. (The optional part is commented out in the raw template file, and will not be visible until you modify and uncomment that part.) If you have any questions about this file, or Code of Conduct policies and procedures, please reach out to Mozilla-GitHub-Standards+CoC@mozilla.com. |
||
---|---|---|
.circleci | ||
pywebpush | ||
.coveragerc | ||
.editorconfig | ||
.gitignore | ||
.travis.yml | ||
CHANGELOG.md | ||
CODE_OF_CONDUCT.md | ||
LICENSE | ||
MANIFEST.in | ||
README.md | ||
README.rst | ||
convert_readme.sh | ||
requirements.txt | ||
setup.cfg | ||
setup.py | ||
test-requirements.txt |
README.md
Webpush Data encryption library for Python
This is a work in progress. This library is available on pypi as pywebpush. Source is available on github.
Installation
You'll need to run python virtualenv
.
Then
bin/pip install -r requirements.txt
bin/python setup.py develop
Usage
In the browser, the promise handler for registration.pushManager.subscribe() returns a PushSubscription object. This object has a .toJSON() method that will return a JSON object that contains all the info we need to encrypt and push data.
As illustration, a subscription_info
object may look like:
{"endpoint": "https://updates.push.services.mozilla.com/push/v1/gAA...", "keys": {"auth": "k8J...", "p256dh": "BOr..."}}
How you send the PushSubscription data to your backend, store it referenced to the user who requested it, and recall it when there's a new push subscription update is left as an exercise for the reader.
Sending Data using webpush()
One Call
In many cases, your code will be sending a single message to many recipients. There's a "One Call" function which will make things easier.
from pywebpush import webpush
webpush(subscription_info,
data,
vapid_private_key="Private Key or File Path[1]",
vapid_claims={"sub": "mailto:YourEmailAddress"})
This will encode data
, add the appropriate VAPID auth headers if required and send it to the push server identified
in the subscription_info
block.
Parameters
subscription_info - The dict
of the subscription info (described above).
data - can be any serial content (string, bit array, serialized JSON, etc), but be sure that your receiving
application is able to parse and understand it. (e.g. data = "Mary had a little lamb."
)
content_type - specifies the form of Encryption to use, either 'aes128gcm'
or the deprecated 'aesgcm'
. NOTE that
not all User Agents can decrypt 'aesgcm'
, so the library defaults to the RFC 8188 standard form.
vapid_claims - a dict
containing the VAPID claims required for authorization (See
py_vapid for more details). If aud
is not specified,
pywebpush will attempt to auto-fill from the endpoint
.
vapid_private_key - Either a path to a VAPID EC2 private key PEM file, or a string containing the DER representation.
(See py_vapid for more details.) The private_key
may be
a base64 encoded DER formatted private key, or the path to an OpenSSL exported private key file.
e.g. the output of:
openssl ecparam -name prime256v1 -genkey -noout -out private_key.pem
Example
from pywebpush import webpush, WebPushException
try:
webpush(
subscription_info={
"endpoint": "https://push.example.com/v1/12345",
"keys": {
"p256dh": "0123abcde...",
"auth": "abc123..."
}},
data="Mary had a little lamb, with a nice mint jelly",
vapid_private_key="path/to/vapid_private.pem",
vapid_claims={
"sub": "mailto:YourNameHere@example.org",
}
)
except WebPushException as ex:
print("I'm sorry, Dave, but I can't do that: {}", repr(ex))
# Mozilla returns additional information in the body of the response.
if ex.response and ex.response.json():
extra = ex.response.json()
print("Remote service replied with a {}:{}, {}",
extra.code,
extra.errno,
extra.message
)
Methods
If you expect to resend to the same recipient, or have more needs than just sending data quickly, you
can pass just wp = WebPusher(subscription_info)
. This will return a WebPusher
object.
The following methods are available:
.send(data, headers={}, ttl=0, gcm_key="", reg_id="", content_encoding="aes128gcm", curl=False, timeout=None)
Send the data using additional parameters. On error, returns a WebPushException
Parameters
data Binary string of data to send
headers A dict
containing any additional headers to send
ttl Message Time To Live on Push Server waiting for the client to reconnect (in seconds)
gcm_key Google Cloud Messaging key (if using the older GCM push system) This is the API key obtained from the Google Developer Console.
reg_id Google Cloud Messaging registration ID (will be extracted from endpoint if not specified)
content_encoding ECE content encoding type (defaults to "aes128gcm")
curl Do not execute the POST, but return as a curl
command. This will write the encrypted content to a local file
named encrpypted.data
. This command is meant to be used for debugging purposes.
timeout timeout for requests POST query. See requests documentation.
Example
to send from Chrome using the old GCM mode:
WebPusher(subscription_info).send(data, headers, ttl, gcm_key)
.encode(data, content_encoding="aes128gcm")
Encode the data
for future use. On error, returns a WebPushException
Parameters
data Binary string of data to send
content_encoding ECE content encoding type (defaults to "aes128gcm")
Example
encoded_data = WebPush(subscription_info).encode(data)