Как встроенный, так и pyopenssl не работают с cherrypy

#python #python-3.x #ssl #cherrypy #pyopenssl

#python #python-3.x #ssl #cherrypy #pyopenssl

Вопрос:

Я защитил свой веб-сервис cherrypy несколько недель назад на своем старом компьютере. Затем у меня возникли проблемы, поэтому я экспортировал свои коды в новый. До этого все работало отлично. Теперь, когда я использую встроенный ssl, моя веб-страница перестает отвечать, потому что cherrypy не отвечает (даже в терминале, он снова работает только тогда, когда я изменяю код) после некоторых запросов. Если я использую pyopenssl, все отлично работает на моем ПК. Если я пытаюсь подключиться с другого компьютера или со своего смартфона / планшета, я получаю эту ошибку:

     "/usr/local/lib/python3.8/dist-packages/OpenSSL/SSL.py", line 1540, in _raise_ssl_error
    raise WantWriteError() 
    OpenSSL.SSL.WantWriteError
 

Это происходит после того, как я пытаюсь вернуть изображения, даже маленькие, как значок веб-сайта.
Вот мой код, я следовал документации cherrypy:

     # MAIN
if __name__ == "__main__":
    conf = {
            '/':{
                    'request.dispatch':cherrypy.dispatch.MethodDispatcher(),
                    'tools.staticdir.root': os.path.abspath(os.getcwd()),
                    'tools.sessions.on':True,
                    'tools.sessions.secure' : True,
                    'tools.sessions.httponly' : True,
                    'tools.secureheaders.on' : True
                    
                },
            '/favicon.ico':
            {
                'tools.staticfile.on': True,
                'tools.staticfile.filename': os.path.abspath(os.getcwd())   '/favicon.ico'
            },

            '/js':{
                    'tools.staticdir.on': True,
                    'tools.staticdir.dir':'./js'
                },
            '/css':{
                    'tools.staticdir.on': True,
                    'tools.staticdir.dir':'./css'
                },
            '/css/Resources':{
                    'tools.staticdir.on': True,
                    'tools.staticdir.dir':'./css/Resources'
                }
    }
    porta = 443 #porta usata
    ip = get_ip() #funzione che prende l'ip del pc

    #inizializzo cherrypy
    cherrypy.tree.mount(SleepRepository(), '/', conf)

        # if hasattr(app, 'toolboxes'):
        # # CherryPy 3.1 
        #   app.toolboxes['secureheaders'] = secureheaders.newauthtools

    cherrypy.config.update({'server.socket_host': ip })      
    cherrypy.config.update({'server.socket_port': porta}) 
    cherrypy.config.update({'server.max_request_body_size' : 35971520000}) #aumento il massimo in MB che posso ricevere
    cherrypy.server.ssl_module = 'pyopenssl'
    cherrypy.server.ssl_certificate = "cert.pem"
    cherrypy.server.ssl_private_key = "privkey.pem"
    cherrypy.engine.start()
    cherrypy.engine.block()
 

Об ошибке я нахожу поток, который предлагает изменить строку библиотеки, но он не работает одинаково… У кого-нибудь есть идея?

Ответ №1:

Да! У меня была такая же проблема с изображениями, и я нашел ответ здесь: https://github.com/cherrypy/cheroot/issues/245

Это должно быть исправлено в более новых версиях cheroot, но предоставляется патч. В makefile.py замените метод BufferedWriter._flush_unlocked() на:

 import OpenSSL
def _flush_unlocked(self):
self._checkClosed('flush of closed file')
while self._write_buf:
    try:
        # ssl sockets only except 'bytes', not bytearrays
        # so perhaps we should conditionally wrap this for perf?
        n = self.raw.write(self._write_buf)
    except io.BlockingIOError as e:
        n = e.characters_written
    except (OpenSSL.SSL.WantReadError,OpenSSL.SSL.WantWriteError, OpenSSL.SSL.WantX509LookupError) as e:
        n = 0
    del self._write_buf[:n]

BufferedWriter._flush_unlocked = _flush_unlocked
 

В том же потоке было другое предложение, изменение одной строки, которое у меня не сработало. Возможно, вы нашли то же самое предложение, но это сработало для меня.

Комментарии:

1. Спасибо, но я перешел на flask, потому что мне нужно было завершить свой проект… Но я думаю, что это может быть полезно в любом случае 🙂