Spaces:
Runtime error
Runtime error
import json | |
import logging | |
import os | |
import sys | |
import certifi | |
from bottle import run, response, Bottle, request, ServerAdapter | |
from bottle_plugins.error_plugin import error_plugin | |
from bottle_plugins.logger_plugin import logger_plugin | |
from bottle_plugins import prometheus_plugin | |
from dtos import V1RequestBase | |
import flaresolverr_service | |
import utils | |
class JSONErrorBottle(Bottle): | |
""" | |
Handle 404 errors | |
""" | |
def default_error_handler(self, res): | |
response.content_type = 'application/json' | |
return json.dumps(dict(error=res.body, status_code=res.status_code)) | |
app = JSONErrorBottle() | |
def index(): | |
""" | |
Show welcome message | |
""" | |
res = flaresolverr_service.index_endpoint() | |
return utils.object_to_dict(res) | |
def health(): | |
""" | |
Healthcheck endpoint. | |
This endpoint is special because it doesn't print traces | |
""" | |
res = flaresolverr_service.health_endpoint() | |
return utils.object_to_dict(res) | |
def controller_v1(): | |
""" | |
Controller v1 | |
""" | |
req = V1RequestBase(request.json) | |
res = flaresolverr_service.controller_v1_endpoint(req) | |
if res.__error_500__: | |
response.status = 500 | |
return utils.object_to_dict(res) | |
if __name__ == "__main__": | |
# check python version | |
if sys.version_info < (3, 9): | |
raise Exception("The Python version is less than 3.9, a version equal to or higher is required.") | |
# fix for HEADLESS=false in Windows binary | |
# https://stackoverflow.com/a/27694505 | |
if os.name == 'nt': | |
import multiprocessing | |
multiprocessing.freeze_support() | |
# fix ssl certificates for compiled binaries | |
# https://github.com/pyinstaller/pyinstaller/issues/7229 | |
# https://stackoverflow.com/questions/55736855/how-to-change-the-cafile-argument-in-the-ssl-module-in-python3 | |
os.environ["REQUESTS_CA_BUNDLE"] = certifi.where() | |
os.environ["SSL_CERT_FILE"] = certifi.where() | |
# validate configuration | |
log_level = os.environ.get('LOG_LEVEL', 'info').upper() | |
log_html = utils.get_config_log_html() | |
headless = utils.get_config_headless() | |
server_host = os.environ.get('HOST', '0.0.0.0') | |
server_port = int(os.environ.get('PORT', 8191)) | |
# configure logger | |
logger_format = '%(asctime)s %(levelname)-8s %(message)s' | |
if log_level == 'DEBUG': | |
logger_format = '%(asctime)s %(levelname)-8s ReqId %(thread)s %(message)s' | |
logging.basicConfig( | |
format=logger_format, | |
level=log_level, | |
datefmt='%Y-%m-%d %H:%M:%S', | |
handlers=[ | |
logging.StreamHandler(sys.stdout) | |
] | |
) | |
# disable warning traces from urllib3 | |
logging.getLogger('urllib3').setLevel(logging.ERROR) | |
logging.getLogger('selenium.webdriver.remote.remote_connection').setLevel(logging.WARNING) | |
logging.getLogger('undetected_chromedriver').setLevel(logging.WARNING) | |
logging.info(f'FlareSolverr {utils.get_flaresolverr_version()}') | |
logging.debug('Debug log enabled') | |
# Get current OS for global variable | |
utils.get_current_platform() | |
# test browser installation | |
flaresolverr_service.test_browser_installation() | |
# start bootle plugins | |
# plugin order is important | |
app.install(logger_plugin) | |
app.install(error_plugin) | |
prometheus_plugin.setup() | |
app.install(prometheus_plugin.prometheus_plugin) | |
# start webserver | |
# default server 'wsgiref' does not support concurrent requests | |
# https://github.com/FlareSolverr/FlareSolverr/issues/680 | |
# https://github.com/Pylons/waitress/issues/31 | |
class WaitressServerPoll(ServerAdapter): | |
def run(self, handler): | |
from waitress import serve | |
serve(handler, host=self.host, port=self.port, asyncore_use_poll=True) | |
run(app, host=server_host, port=server_port, quiet=True, server=WaitressServerPoll) | |