Привет,
Я пытаюсь настроить пользовательского рабочего для получения информации о сертификате клиента с сервера, а затем получить ее в моем приложении Flask следующим образом:
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)
Я получаю следующее исключение:
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
Я пробовал несколько вещей, чтобы исправить это, например, я попытался установить worker_class_str
в файле gunicorn_options.py
, но это не помогло. Затем я начал копаться в коде фактического пакета и обнаружил, что когда я изменил файл gunicorn/arbiter.py
чтобы закомментировать строку: self.log.info("Using worker: %s", self.cfg.worker_class_str)
все работает отлично, CustomSyncWorker загружается нормально и выполняет свою работу, так как предполагается установка заголовка X-USER и всего остального.
Это ошибка? Или я просто делаю что-то в корне не так? Я полагаю, что не должен брать на себя изменение кода локально, чтобы заставить все работать ...
Я думаю, вам нужно передать строку в worker_class
. Так меняется
worker_class = CustomSyncWorker
к
worker_class = 'mypackage.client_auth_worker.CustomSyncWorker'
решит вашу проблему.
И обратите внимание, что это уже задокументировано на http://docs.gunicorn.org/en/stable/settings.html#worker -class
При желании вы можете предоставить своего рабочего, указав Gunicorn путь Python к подклассу gunicorn.workers.base.Worker. Этот альтернативный синтаксис загрузит класс gevent: gunicorn.workers.ggevent.GeventWorker.
Конечно, мы всегда можем улучшить документацию, если у вас есть лучшее предложение.
Спасибо за отчет!
Думаю, я пробовал это, и это не сработало, однако я не уверен, и, возможно, я написал строку по-другому (например, в формате "mypackage.client_auth_worker:CustomSyncWorker"
). Мне нужно будет проверить, когда я вернусь домой сегодня вечером.
Помимо этого, я бы порекомендовал поместить прямой пример в документацию или, по крайней мере, где-нибудь еще (где вы считаете это подходящим) просто потому, что я видел эту документацию, и было неясно, что я должен был сделать в случае файл конфигурации Python. В итоге я провел кучу проб и ошибок, что привело к тому, что я получил рабочую версию, которую я опубликовал после того, как прокомментировал распечатку.
Спасибо, что связались со мной так быстро!
ОК, подтвердил, что это сработало. Спасибо вам за помощь!
Самый полезный комментарий
Я думаю, вам нужно передать строку в
worker_class
. Так меняетсяк
решит вашу проблему.