Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rest service, disconnect log and enhanced notifications #40

Open
wants to merge 51 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
b167479
ran autopep8
Jan 24, 2013
247bce5
use json if available
Jan 25, 2013
f1ccd6d
feedback timestamps are in utc
Jan 25, 2013
63a78d9
ignore twistd run files
Jan 25, 2013
005dcc1
rest service, disconnection log, enhanced notifications
Jan 25, 2013
2418a49
forgot some types
Jan 25, 2013
0cc522b
remove print
Jan 25, 2013
beb7ad5
remove unneeded code
Jan 25, 2013
cb933dc
upgrade twisted requirement (because of the new(er) web stuff)
Jan 25, 2013
fd057a2
first brush at new REST-based Python client
Jan 25, 2013
99cd511
added some more docs
Jan 25, 2013
a7bdc7a
first brush at change list for 0.5.0
Jan 25, 2013
aff1106
example tac is now the tac you should use; updated
Jan 25, 2013
855073b
stupid import error
Jan 25, 2013
a0757f1
fixes #28 - callback returns None
Jan 25, 2013
8686025
note fixed #28
Jan 25, 2013
583e419
readme checkpoint - still plenty more to write
Jan 26, 2013
b3c66b5
another checkpoint on README - trying to nail down rest docs formatting
Jan 26, 2013
3b0004c
formatting test
Jan 26, 2013
124a2e8
formatting test
Jan 26, 2013
44282c7
formatting test
Jan 26, 2013
55c162f
formatting test
Jan 26, 2013
59dae30
try a dl
Jan 26, 2013
456a0e0
remove trailing slash
Jan 30, 2013
dd62742
it's 2013!
Jan 30, 2013
6eb0b83
fix problem that ujson.dumps doesn't have separators keyword argument
jjyao Apr 18, 2013
b63ec75
Merge pull request #46 from JiajunYao/fix_ujson_dumps
Apr 18, 2013
da23e3e
Fix typo
jjyao Apr 19, 2013
548a231
Support languages other than English
jjyao Apr 19, 2013
ac49a22
Merge pull request #47 from JiajunYao/fix_typo
Apr 19, 2013
d346827
Clear disconnection events after getting them
jjyao Apr 30, 2013
42e6a75
Merge pull request #48 from JiajunYao/clear_disconneciton_events
Apr 30, 2013
7fc2611
Fix a bug: ClientError __init__() needs 3 arguments
jjyao May 6, 2013
241e9b1
Merge pull request #49 from JiajunYao/ClientError_needs_three_arguments
May 8, 2013
d8fc5cf
Add an option: bind pyapns to a specified IP address
jjyao Jul 2, 2013
ffc95b0
Merge pull request #51 from JiajunYao/bind-to-specified-ip-address
Jul 2, 2013
d71abcc
Add options to config log file
jjyao Jul 18, 2013
68f5079
Merge pull request #52 from jjyao/log
Jul 19, 2013
bf7cecf
Add requests package to setup.py.
jwatson Sep 5, 2013
f4c2051
Fix crash when sending UTF-8 characters.
jwatson Sep 5, 2013
71b70c2
Merge pull request #56 from Mapkin/v50
Sep 27, 2013
50ed6a3
Attempt to fix unreliable write to APNS after connection has been est…
Oct 16, 2013
4627807
Remove tcp settings that were enabled for testing
Oct 16, 2013
802dcf3
Applying changes from code review notes on better datetime/timedelta …
Oct 16, 2013
5376e60
Merge pull request #59 from bdavissl/apple-timed-disconnect
Oct 18, 2013
7f813ca
Fix for leaking file descriptor issue
Nov 11, 2013
cf904aa
Merge pull request #61 from bdavissl/file-descriptor-leak
Nov 11, 2013
0313d56
Add Status Code 10: Shutdown
omenar May 30, 2014
b3119ec
Merge pull request #66 from omenar/shutdown_code
samuraisam Jun 2, 2014
fbf7999
Use TLSv1 instead of SSLv3
Nov 5, 2015
1116b58
Merge pull request #79 from noodlecake/switch_connection_method
samuraisam Nov 5, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ build/**
dist/**
.idea
atlassian-ide-plugin.xml
twistd.log
twistd.pid
44 changes: 44 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
version 0.5.0 - 2013-01-25
==========================

There is lots of new stuff here but this release is backwards compatible. The
REST interface operates on a different default port and runs completey in
paralell with the XML-RPC one. That said, REST is the way forward and all new
features will be added to that server.

New:

* An all-new REST interface that simplifies access to pyapns's functionality.

The XML-RPC server will be depreciated over the coming years. Next year it
will be "depreciated" as in it will start giving off warnings and the year
after it will likely be entirely removed.

* REST interface uses Apple's new "enhanced" notification format which has
the ability to send back errors in the event Apple severs the connection
to pyapns (which can happen for a number of reasons).

* A disconnection log which will pair disconnection events with the
notifications at fault. This will allow you to remove offending tokens
and notifications.

* The new Python client uses the very fine requests library which provides
several advantages over the old XML-RPC library principally: connection
keep-alive and reuse and connection pooling.

Fixed Bugs:

* Fixed #31/#26 - Token blacklisting - we will not blacklist tokens as it's
not the job of this daemon to persist that kind of state. We however now
give you the tools to blacklist tokens should you wish to do so.

* Fixed #14 - Apple Dropping Connection - this can happen for any number
of reasons, by using the new REST service you can get an idea of why.

* Fixed #10 - reprovisioning - while this issue isn't specifically to allow
reprovisioning, the reason @mikeytrw wanted the feature was to replace
certs, which is now possible.

* Fixed #28 - sending multiple notifications after a disconnect fails -
simply fixed the way the deferred was handeled

version 0.4.0 - 2012-02-14
==========================

Expand Down
2 changes: 1 addition & 1 deletion COPYING
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2012 Samuel Sutch
Copyright (c) 2013 Samuel Sutch

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
477 changes: 139 additions & 338 deletions README.md

Large diffs are not rendered by default.

40 changes: 8 additions & 32 deletions example_conf.json
Original file line number Diff line number Diff line change
@@ -1,41 +1,17 @@
{
"host": "localhost",
"log_file_name": "pyapns.log",
"log_file_dir": ".",
"log_file_rotate_length": 1000000000,
"log_file_max_rotate": 10,
"port": 7077,
"rest_port": 8088,
"autoprovision": [
{
"app_id": "sandbox:com.ficture.ficturebeta",
"cert": "/Users/sam/dev/ficture/push_certs/development-com.ficture.ficturebeta.pem",
"app_id": "com.example.myapp",
"cert": "/path/to/cert.pem",
"environment": "sandbox",
"timeout": 15
},
{
"app_id": "production:com.ficture.ficturebeta",
"cert": "/Users/sam/dev/ficture/push_certs/production-com.ficture.ficturebeta.pem",
"environment": "production",
"timeout": 15
},
{
"app_id": "sandbox:com.ficture.ficturebeta2",
"cert": "/Users/sam/dev/ficture/push_certs/development-com.ficture.ficturebeta2.pem",
"environment": "sandbox",
"timeout": 15
},
{
"app_id": "production:com.ficture.ficturebeta2",
"cert": "/Users/sam/dev/ficture/push_certs/production-com.ficture.ficturebeta2.pem",
"environment": "production",
"timeout": 15
},
{
"app_id": "sandbox:com.ficture.ficturebeta3",
"cert": "/Users/sam/dev/ficture/push_certs/development-com.ficture.ficturebeta3.pem",
"environment": "sandbox",
"timeout": 15
},
{
"app_id": "production:com.ficture.ficturebeta3",
"cert": "/Users/sam/dev/ficture/push_certs/production-com.ficture.ficturebeta3.pem",
"environment": "production",
"timeout": 15
}
]
}
36 changes: 0 additions & 36 deletions example_tac.tac

This file was deleted.

96 changes: 96 additions & 0 deletions pyapns.tac
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# CONFIG FILE LOCATION
# relative to this file or absolute path

config_file = '/path/to/config/pyapns_conf.json'

# you don't need to change anything below this line really

import twisted.application, twisted.web, twisted.application.internet
from twisted.python.logfile import LogFile
from twisted.python.log import ILogObserver, FileLogObserver
import pyapns.server, pyapns._json
import pyapns.rest_service, pyapns.model
import os

config = {}

if os.path.exists(os.path.abspath(config_file)):
with open(os.path.abspath(config_file)) as f:
config.update(pyapns._json.loads(f.read()))
else:
print 'No config file loaded. Alter the `config_file` variable at', \
'the top of this file to set one.'

xml_service = pyapns.server.APNSServer()

# get automatic provisioning
if 'autoprovision' in config:
for app in config['autoprovision']:
# for XML-RPC
xml_service.xmlrpc_provision(app['app_id'], app['cert'],
app['environment'], app['timeout'])
# for REST
pyapns.model.AppRegistry.put(
app['app_id'], app['environment'], app['cert'],
timeout=app['timeout']
)

if 'log_file_name' in config:
log_file_name = config['log_file_name']
else:
log_file_name = 'twistd.log'

if 'log_file_dir' in config:
log_file_dir = config['log_file_dir']
else:
log_file_dir = '.'

if 'log_file_rotate_length' in config:
log_file_rotate_length = config['log_file_rotate_length']
else:
log_file_rotate_length = 1000000

if 'log_file_mode' in config:
log_file_mode = config['log_file_mode']
else:
log_file_mode = None

if 'log_file_max_rotate' in config:
log_file_max_rotate = config['log_file_max_rotate']
else:
log_file_max_rotate = None

application = twisted.application.service.Application("pyapns application")
logfile = LogFile(log_file_name, log_file_dir, log_file_rotate_length, log_file_mode, log_file_max_rotate)
application.setComponent(ILogObserver, FileLogObserver(logfile).emit)

if 'host' in config:
host = config['host']
else:
host = ''

# XML-RPC server support ------------------------------------------------------

if 'port' in config:
port = config['port']
else:
port = 7077

resource = twisted.web.resource.Resource()
resource.putChild('', xml_service)

site = twisted.web.server.Site(resource)

server = twisted.application.internet.TCPServer(port, site, interface=host)
server.setServiceParent(application)

# rest service support --------------------------------------------------------
if 'rest_port' in config:
rest_port = config['rest_port']
else:
rest_port = 8088

site = twisted.web.server.Site(pyapns.rest_service.default_resource)

server = twisted.application.internet.TCPServer(rest_port, site, interface=host)
server.setServiceParent(application)
2 changes: 1 addition & 1 deletion pyapns/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .client import notify, provision, feedback, configure__version__ = "0.4.0"__author__ = "Samuel Sutch"__license__ = "MIT"__copyright__ = "Copyrighit 2012 Samuel Sutch"
from .client import notify, provision, feedback, configure__version__ = "0.5.0"__author__ = "Samuel Sutch"__license__ = "MIT"__copyright__ = "Copyrighit 2013 Samuel Sutch"
Expand Down
41 changes: 27 additions & 14 deletions pyapns/_json.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
try:
import json
try:
import ujson # try for ujson first because it rocks and is fast as hell
class ujsonWrapper(object):
def dumps(self, obj, *args, **kwargs):
# ujson dumps method doesn't have separators keyword argument
if 'separators' in kwargs:
del kwargs['separators']
return ujson.dumps(obj, *args, **kwargs)

def loads(self, str, *args, **kwargs):
return ujson.loads(str, *args, **kwargs)
json = ujsonWrapper()
except ImportError:
import json
except (ImportError, NameError):
try:
from django.utils import simplejson as json
except (ImportError, NameError):
import simplejson as json
try:
from django.utils import simplejson as json
except (ImportError, NameError):
import simplejson as json
try:
json.dumps
json.loads
json.dumps
json.loads
except AttributeError:
try: # monkey patching for python-json package
json.dumps = lambda obj, *args, **kwargs: json.write(obj)
json.loads = lambda str, *args, **kwargs: json.read(str)
except AttributeError:
raise ImportError('Could not load an apropriate JSON library '
'currently supported are simplejson, '
'python2.6+ json and python-json')
try: # monkey patching for python-json package
json.dumps = lambda obj, *args, **kwargs: json.write(obj)
json.loads = lambda str, *args, **kwargs: json.read(str)
except AttributeError:
raise ImportError('Could not load an apropriate JSON library '
'currently supported are simplejson, '
'python2.6+ json and python-json')

loads = json.loads
dumps = json.dumps
Loading