olucurious / PyFCM

Python client for FCM - Firebase Cloud Messaging (Android, iOS and Web)
http://olucurious.github.io/PyFCM/
MIT License
803 stars 206 forks source link

Python SSL recursion error -> super(SSLContext, SSLContext).options.__set__(self, value) requests: RecursionError: maximum recursion depth exceeded #274

Closed mm360x closed 2 years ago

mm360x commented 4 years ago

0

I am using Python 3.8.3 My program is a chat application using python-socketio with a redis queue using eventlet server in a docker container and load balanced with nginx The program works fine on my local computer But when I try to run in an an AWS EC2 linux instance, the pyfcm library when trying to send a Push Notification does not work and I get an ssl error. I am using eventlet.monkeypatch(socket=True) at the start of the program

This is the error

Exception in thread Thread-8:
    container    | Traceback (most recent call last):
    container    |   File "/usr/local/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    container    |     self.run()
    container    |   File "/usr/local/lib/python3.8/threading.py", line 870, in run
    container    |     self._target(*self._args, **self._kwargs)
    container    |   File "/usr/local/lib/python3.8/site-packages/socketio/server.py", line 679, in _handle_event_internal
    container    |     r = server._trigger_event(data[0], namespace, sid, *data[1:])
    container    |   File "/usr/local/lib/python3.8/site-packages/socketio/server.py", line 708, in _trigger_event
    container    |     return self.handlers[namespace][event](*args)
    container    |   File "server.py", line 37, in send_message_event
    container    |     result = push_service.notify_single_device(registration_id=mid['apns_result']['registration_id'], message_title=mid['apns_result']['message_title'], message_body=mid['apns_result']['message_body'])
    container    |   File "/usr/local/lib/python3.8/site-packages/pyfcm/fcm.py", line 116, in notify_single_device
    container    |     self.send_request([payload], timeout)
    container    |   File "/usr/local/lib/python3.8/site-packages/pyfcm/baseapi.py", line 312, in send_request
    container    |     response = self.do_request(payload, timeout)
    container    |   File "/usr/local/lib/python3.8/site-packages/pyfcm/baseapi.py", line 302, in do_request
    container    |     response = self.requests_session.post(self.FCM_END_POINT, data=payload, timeout=timeout)
    container    |   File "/usr/local/lib/python3.8/site-packages/requests/sessions.py", line 578, in post
    container    |     return self.request('POST', url, data=data, json=json, **kwargs)
    container    |   File "/usr/local/lib/python3.8/site-packages/requests/sessions.py", line 530, in request
    container    |     resp = self.send(prep, **send_kwargs)
    container    |   File "/usr/local/lib/python3.8/site-packages/requests/sessions.py", line 643, in send
    container    |     r = adapter.send(request, **kwargs)
    container    |   File "/usr/local/lib/python3.8/site-packages/requests/adapters.py", line 439, in send
    container    |     resp = conn.urlopen(
    container    |   File "/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 670, in urlopen
    container    |     httplib_response = self._make_request(
    container    |   File "/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 381, in _make_request
    container    |     self._validate_conn(conn)
    container    |   File "/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 976, in _validate_conn
    container    |     conn.connect()
    container    |   File "/usr/local/lib/python3.8/site-packages/urllib3/connection.py", line 342, in connect
    container    |     self.ssl_context = create_urllib3_context(
    container    |   File "/usr/local/lib/python3.8/site-packages/urllib3/util/ssl_.py", line 276, in create_urllib3_context
    container    |     context.options |= options
    container    |   File "/usr/local/lib/python3.8/ssl.py", line 602, in options
    container    |     super(SSLContext, SSLContext).options.__set__(self, value)
    container    |   File "/usr/local/lib/python3.8/ssl.py", line 602, in options
    container    |     super(SSLContext, SSLContext).options.__set__(self, value)
    container    |   File "/usr/local/lib/python3.8/ssl.py", line 602, in options
    container    |     super(SSLContext, SSLContext).options.__set__(self, value)
    container    |   [Previous line repeated 481 more times]
    container    | RecursionError: maximum recursion depth exceeded

My Program, I have tried monkeypatching() before any other imports but then my websocket connections do not work as well as my databse connection times out. I have also tried the pyfcm import before and after the monkeypatch but nothing seems to work

import eventlet, socketio, save_history, pyfcm
from pyfcm import FCMNotification
eventlet.monkey_patch(socket= True)

#sio = socketio.Server()
mgr = socketio.RedisManager('redis://redis:PORT/0')
sio = socketio.Server(client_manager=mgr, async_mode='eventlet', logger=True)
app = socketio.WSGIApp(sio)

# Join Room when client comes online
@sio.on('subscribe')
def join_room_event(sid,data):
    user = data['user_id']
    channel = data['channel']
    if save_history.check_user_channel(channel, user):
        sio.enter_room(sid,channel)
        sio.logger.log (level=20,msg="User " + str(user) + " in channel: " + str(channel) + " Joined and Verified with SID " + str(sid))
        return True
    else:
        sio.logger.log (level=20,msg="User " + str(user) + " NOT in channel: " + str(channel) + " with SID " + str(sid))
        return False

@sio.on('send_message')
def send_message_event(sid, data):
    channel_id = data['channel']
    user = data['user_id']
    message = data['message']
    if user and channel_id and message:

    mid = save_history.save_message(channel_id, int(user), message)
    data['message_id'] = mid['message_id']
    data['time_sent'] = mid['time_sent']
    sio.logger.log (level=20,msg='{Message: ' + message + ' with MID: ' +str(mid)+ ' sent by ' + str(user) + ' in channel ' + str(channel_id) + '}')
    if mid['apns_result'] != 'no_apns':
        push_service = FCMNotification(api_key='<api-key>')
        result = push_service.notify_single_device(registration_id=mid['apns_result']['registration_id'], message_title=mid['apns_result']['message_title'], message_body=mid['apns_result']['message_body'])
        sio.logger.log (level=20,msg=result)
    sio.emit('receive_message', data, room=channel_id)
    return data 
else:
    sio.emit('receive_message', { 'message' : "All params not present" } , room=channel_id)
    return { 'message' : "All params not present" }

Any solutions will be greatly appreciated! Thank you

jerryz1982 commented 4 years ago

i had the same issue with python3.6, running pyfcm on python3.5 doesn't have this issue.

jerryz1982 commented 3 years ago

In python3.6 and eventlet > 0.17.4, this issue will happen. https://github.com/eventlet/eventlet/issues/371

jerryz1982 commented 3 years ago

Use eventlet.monkey_patch as early as possible in the code fixed the issue.

mm360x commented 3 years ago

Using the eventlet wrapper for SSL protocols and upgrading to version 0.26 worked for me for all libraries