djacobs / PyAPNs

Python library for interacting with the Apple Push Notification service (APNs)
http://pypi.python.org/pypi/apns/
MIT License
1.22k stars 374 forks source link

Not working on App Engine #42

Closed Mina-H-Samy closed 10 years ago

Mina-H-Samy commented 10 years ago

Library works fine in a local python script but not in App Engine. I always get

    self._ssl = wrap_socket(self._socket, self.key_file, self.cert_file)
TypeError: 'NoneType' object is not callable

Did anybody get this library working with AppEngine?

Mina-H-Samy commented 10 years ago

ok I finally got it working thanks to this project https://github.com/GarettRogers/appengine-apns-gcm

Here's what you need to do:

1) In app.yaml libraries section add ssl so that it looks like this

libraries:
- name: webapp2
  version: "2.5.2"
- name: ssl
  version: latest

2) in apns.py (this library)

add import StringIO to the list of imports

3) in apns.py

change the line

self._ssl = wrap_socket(self._socket, self.key_file, self.cert_file)

to

self._ssl = wrap_socket(self._socket, server_side=False, keyfile=StringIO.StringIO(self.key_file), certfile=StringIO.StringIO(self.cert_file))

4) Make sure that your key file does not have a passphrase so that it can send automatically (potential security problem?) If your key.pem already has a passphrase you can remove it by doing openssl rsa -in key.pem -out newkey.pem

5) Open your cert.pem and key.pem in a text editor and copy their contents to python strings in your app engine script so it looks something like this

apnsCert = '''-----BEGIN CERTIFICATE-----
.........................................................................
-----END CERTIFICATE-----
'''

apnsKey = '''-----BEGIN RSA PRIVATE KEY-----
........................................................................
-----END RSA PRIVATE KEY-----
'''

6) finally call the APNs constructor like this apns = APNs(cert_file=apnsCert, key_file=apnsKey) where apnsCert and apnsKey are the strings you created in step 5 of course.

kaansoral commented 10 years ago

Let me just add that one must provide a local file url in order to make it work on App Engine's SDK - so instead of StringIO.StringIO(string) just a local file path does the job at the self._ssl / wrap_socket override