Olá,
Estou tentando definir um trabalhador personalizado para recuperar informações de certificado do cliente do servidor e, em seguida, colocá-las em meu aplicativo Flask da seguinte forma:
gunicorn_options.py:
import multiprocessing
import os
from mypackage.client_auth_worker import CustomSyncWorker
def config_dir():
return os.path.dirname(os.path.realpath(__file__))
bind = "0.0.0.0:8000"
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = CustomSyncWorker
timeout = 30
ca_certs = os.path.join(config_dir(), 'ca.cert.pem')
certfile = os.path.join(config_dir(), 'server.cert.pem')
keyfile = os.path.join(config_dir(), 'server.key.pem')
cert_reqs = 2
do_handshake_on_connect = True
custom_auth_worker.py:
from gunicorn.workers.sync import SyncWorker
class CustomSyncWorker(SyncWorker):
def handle_request(self, listener, req, client, addr):
subject = dict(client.getpeercert().get('subject')[0])
headers = dict(req.headers)
headers['X-USER'] = subject.get('commonName')
print(headers)
req.headers = list(headers.items())
super(CustomSyncWorker, self).handle_request(listener, req, client, addr)
Continuo recebendo a seguinte exceção:
File "/Users/me/.virtualenvs/mypackage/lib/python3.5/site-packages/gunicorn/arbiter.py", line 162, in start
self.log.info("Using worker: %s", self.cfg.worker_class_str)
File "/Users/me/.virtualenvs/mypackage/lib/python3.5/site-packages/gunicorn/config.py", line 68, in __getattr__
raise AttributeError("No configuration setting for: %s" % name)
AttributeError: No configuration setting for: worker_class_str
Tentei várias coisas para corrigir isso, por exemplo, tentei definir um worker_class_str
no arquivo gunicorn_options.py
, que não resolveu o problema. Comecei então a pesquisar o código do pacote real e descobri que quando modifiquei o arquivo gunicorn/arbiter.py
para comentar a linha: self.log.info("Using worker: %s", self.cfg.worker_class_str)
tudo funciona perfeitamente bem, o CustomSyncWorker está carregado perfeitamente e faz seu trabalho como deve definir o cabeçalho X-USER e tudo mais.
Isso é um inseto? Ou estou apenas fazendo algo drasticamente errado? Acho que não devo assumir a responsabilidade de modificar o código localmente apenas para forçar as coisas a funcionarem ...
Acho que você precisa passar uma string para worker_class
. Então mudando
worker_class = CustomSyncWorker
para
worker_class = 'mypackage.client_auth_worker.CustomSyncWorker'
resolveria seu problema.
E observe que isso já está documentado em http://docs.gunicorn.org/en/stable/settings.html#worker -class
Opcionalmente, você pode fornecer seu próprio trabalhador fornecendo ao Gunicorn um caminho Python para uma subclasse de gunicorn.workers.base.Worker. Essa sintaxe alternativa carregará a classe gevent: gunicorn.workers.ggevent.GeventWorker.
Claro, podemos sempre melhorar a documentação se você tiver uma sugestão melhor.
Obrigado pelo relatório!
Acho que tentei fazer isso e não funcionou, no entanto, não tenho certeza e posso ter escrito a string de forma diferente (como em um formato "mypackage.client_auth_worker:CustomSyncWorker"
). Terei que verificar quando chegar em casa mais tarde hoje.
Além disso, eu recomendaria colocar um exemplo direto na documentação ou pelo menos em outro lugar (onde você achar apropriado) simplesmente porque eu tinha visto aquela documentação e não estava claro se isso é o que eu deveria ter feito no caso de um arquivo de configuração python. Acabei fazendo um monte de tentativas e erros, o que resultou na obtenção de uma versão funcional que postei depois de comentar a impressão.
Obrigado por voltar para mim tão rapidamente!
OK, confirmado, funcionou. Obrigado pela ajuda!
Comentários muito úteis
Acho que você precisa passar uma string para
worker_class
. Então mudandopara
resolveria seu problema.