I am using PyAPNS to connect to APNs from Python. When running as a stand alone script, all is working fine and push messages get delivered. When running in the Google App E
Not sure if this is still useful or if you found answers elsewhere.
I had a pretty similar issue trying to use the requests
library in pretty standard app engine code.
tl;dr - App Engine patches/provides a sandboxed socket
. The ssl
module snapshots objects from socket
's namespace on its own import. If socket
(and _socket
) is not the correct version when ssl
is imported, ssl
will end up with GAE-patch/sandbox based values for SOL_SOCKET
and SO_TYPE
(probably incorrect), rather than what should have come from a base system installation. If you make sure your copy of socket
(and _socket
) is correct, ssl
will work.
I filed a support ticket with Google and got push-back to implement this.
It's not actually that trivial for me to just swap out the physical socket.py
implementation, so I went the route of this solution instead.
Which got me most of the way there, but the issue still cropped up because of SSL.
I have tested something practically identical to the below code to get SSL working with raw sockets (rather than URLFetch) when making HTTP requests in an App Engine development sandbox (i.e dev_appserver.py
):
import os
def _patch_ssl_support():
# Only patch SSL support if it's local dev.
if not os.environ.get('SERVER_SOFTWARE', '').startswith('Development'):
return
import imp
import inspect
from google.appengine.tools.devappserver2.python import sandbox
# Allow the sandbox to read _ssl and _socket.
sandbox._WHITE_LIST_C_MODULES += ['_socket', '_ssl']
# Use the system socket.
# I used inspect here, but many core modules should work.
# It ultimately depends on your python installation.
runtime_path = os.path.realpath(inspect.getsourcefile(inspect))
runtime_dir = os.path.dirname(runtime_path)
# Patch and reload the socket module implementation.
system_socket = os.path.join(runtime_dir, 'socket.py')
imp.load_source('socket', system_socket)
# Patch and reload the ssl module implementation.
system_ssl = os.path.join(runtime_dir, 'ssl.py')
imp.load_source('ssl', system_ssl)
# Patch and/or reload any other libraries you suspect may have copied values
# from the socket or ssl namespaces.
# Patch SSL support before you do anything else.
_patch_ssl_support()
import webapp2
# Setup app engine application, or something that runs in an app engine runtime:
app = webapp2.WSGIApplication(routes)