mirror of
https://github.com/cryptoadvance/specter-desktop.git
synced 2026-08-13 12:33:29 +02:00
Feature: introducing gunicorn as an alternative WSGI HTTP Server (#1721)
* introducing gunicorn as an alternative WSGI HTTP Server * gunicorn, plain and simple * dependencies for gunicorn * correct dependencies * fix app-context * adding gunicorn cli * add uid to welcome-page * fixing bad take from other PR
This commit is contained in:
parent
cf299ee5b4
commit
0f7677805c
9 changed files with 114 additions and 9 deletions
|
|
@ -25,3 +25,4 @@ cbor==1.0.0
|
|||
mnemonic==0.20
|
||||
cryptography==3.4.7
|
||||
Flask-APScheduler==1.12.3
|
||||
gunicorn==20.1.0
|
||||
|
|
@ -184,6 +184,10 @@ flask_wtf==0.15.1 \
|
|||
--hash=sha256:6ff7af73458f182180906a37a783e290bdc8a3817fe4ad17227563137ca285bf \
|
||||
--hash=sha256:ff177185f891302dc253437fe63081e7a46a4e99aca61dfe086fb23e54fff2dc
|
||||
# via -r requirements.in
|
||||
gunicorn==20.1.0 \
|
||||
--hash=sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e \
|
||||
--hash=sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8
|
||||
# via -r requirements.in
|
||||
hidapi==0.10.1 \
|
||||
--hash=sha256:095798ae1b3d6892fb0eb7ba1ab06054f6fafe6d09bc3714d80fdbf227c98f87 \
|
||||
--hash=sha256:0c92b398f6907654b07f7dbd7e06661abe9ad6119b403eb5fd3c2af4ce66a3b7 \
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import click
|
|||
from .cli_noded import bitcoind, elementsd
|
||||
from .cli_ext import ext
|
||||
from .cli_server import server
|
||||
from .cli_gunicorn import gunicorn
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -59,6 +60,7 @@ def entry_point(config_home, debug=False, tracerpc=False, tracerequests=False):
|
|||
|
||||
|
||||
entry_point.add_command(server)
|
||||
entry_point.add_command(gunicorn)
|
||||
entry_point.add_command(ext)
|
||||
entry_point.add_command(bitcoind)
|
||||
entry_point.add_command(elementsd)
|
||||
|
|
|
|||
65
src/cryptoadvance/specter/cli/cli_gunicorn.py
Normal file
65
src/cryptoadvance/specter/cli/cli_gunicorn.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import logging
|
||||
import multiprocessing
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
import time
|
||||
from os import path
|
||||
from socket import gethostname
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import click
|
||||
from cryptoadvance.specter.gunicorn import SpecterGunicornApp
|
||||
from cryptoadvance.specter.server import create_and_init, create_app, init_app
|
||||
from OpenSSL import SSL, crypto
|
||||
from stem.control import Controller
|
||||
|
||||
from ..server import create_app, init_app
|
||||
from ..specter_error import SpecterError
|
||||
from ..util.tor import start_hidden_service, stop_hidden_services
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@click.group()
|
||||
def cli():
|
||||
pass
|
||||
|
||||
|
||||
@cli.command()
|
||||
def gunicorn():
|
||||
"""uses gunicorn instead of the build in development-server.
|
||||
This works mostly like in https://docs.gunicorn.org/en/latest/run.html just that you use
|
||||
this command rather than gunicorn. As recommended there, everything Application
|
||||
specific needs to be configured via envirnoment Vars. See cryptoadvance.specter.config for
|
||||
how to configure most specter-sepcific things.
|
||||
|
||||
Other than running gunicorn's executable directly, you can't specify command-line
|
||||
paramaters. Here are some configurations you can do:
|
||||
|
||||
```
|
||||
GUNICORN_CMD_ARGS="--bind=127.0.0.1 --workers=3" python3 -m cryptoadvance.specter gunicorn
|
||||
```
|
||||
|
||||
You can use a config file named gunicorn.conf.py in the same directory:
|
||||
|
||||
```
|
||||
workers=10
|
||||
```
|
||||
|
||||
Commandline paramater trums env-var params.
|
||||
You can specify hook functions in the gunicorn.conf.py, see this for a list of them:
|
||||
https://docs.gunicorn.org/en/latest/settings.html#server-hooks
|
||||
|
||||
e.g.:
|
||||
```
|
||||
def on_starting(server):
|
||||
print("Called just before the master process is initialized.")
|
||||
```
|
||||
|
||||
More information directly in the gunicorn-Documentation
|
||||
|
||||
|
||||
"""
|
||||
specter_gunicorn = SpecterGunicornApp(config=None)
|
||||
specter_gunicorn.run()
|
||||
|
|
@ -248,7 +248,8 @@ class CypressTestConfig(TestConfig):
|
|||
|
||||
|
||||
class ProductionConfig(BaseConfig):
|
||||
SECRET_KEY = secrets.token_urlsafe(16)
|
||||
# Injectable, as having a random SECRET-KEY won't work for gunicorn using more than one worker (might have more issues with multiple workers, though)
|
||||
SECRET_KEY = os.getenv("SECRET_KEY", secrets.token_urlsafe(16))
|
||||
# There are some really slow machines out there. Creating a 2/4 multisig on an older MacBookAir
|
||||
# Take already >30secs
|
||||
BITCOIN_RPC_TIMEOUT = float(os.getenv("BITCOIN_RPC_TIMEOUT", "60"))
|
||||
|
|
|
|||
32
src/cryptoadvance/specter/gunicorn.py
Normal file
32
src/cryptoadvance/specter/gunicorn.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import multiprocessing
|
||||
from cryptoadvance.specter.server import init_app, create_app, create_and_init
|
||||
|
||||
from gunicorn.app.wsgiapp import WSGIApplication
|
||||
|
||||
|
||||
class SpecterGunicornApp(WSGIApplication):
|
||||
def __init__(
|
||||
self, config="cryptoadvance.specter.config.ProductionConfig", options=None
|
||||
):
|
||||
"""
|
||||
i guess those are the potential options:
|
||||
usage: __main__.py [-h] [-v] [-c CONFIG] [-b ADDRESS] [--backlog INT] [-w INT] [-k STRING] [--threads INT]
|
||||
[--worker-connections INT] [--max-requests INT] [--max-requests-jitter INT] [-t INT] [--graceful-timeout INT]
|
||||
[--keep-alive INT] [--limit-request-line INT] [--limit-request-fields INT] [--limit-request-field_size INT]
|
||||
[--reload] [--reload-engine STRING] [--reload-extra-file FILES] [--spew] [--check-config] [--print-config]
|
||||
[--preload] [--no-sendfile] [--reuse-port] [--chdir CHDIR] [-D] [-e ENV] [-p FILE] [--worker-tmp-dir DIR]
|
||||
[-u USER] [-g GROUP] [-m INT] [--initgroups] [--forwarded-allow-ips STRING] [--access-logfile FILE]
|
||||
[--disable-redirect-access-to-syslog] [--access-logformat STRING] [--error-logfile FILE] [--log-level LEVEL]
|
||||
[--capture-output] [--logger-class STRING] [--log-config FILE] [--log-syslog-to SYSLOG_ADDR] [--log-syslog]
|
||||
[--log-syslog-prefix SYSLOG_PREFIX] [--log-syslog-facility SYSLOG_FACILITY] [-R] [--statsd-host STATSD_ADDR]
|
||||
[--dogstatsd-tags DOGSTATSD_TAGS] [--statsd-prefix STATSD_PREFIX] [-n STRING] [--pythonpath STRING]
|
||||
[--paste STRING] [--proxy-protocol] [--proxy-allow-from PROXY_ALLOW_IPS] [--keyfile FILE] [--certfile FILE]
|
||||
[--ssl-version SSL_VERSION] [--cert-reqs CERT_REQS] [--ca-certs FILE] [--suppress-ragged-eofs]
|
||||
[--do-handshake-on-connect] [--ciphers CIPHERS] [--paste-global CONF] [--strip-header-spaces]
|
||||
"""
|
||||
self.options = options or {}
|
||||
self.config = config
|
||||
super().__init__()
|
||||
|
||||
def load(self):
|
||||
return create_and_init(self.config)
|
||||
|
|
@ -93,6 +93,8 @@ def create_app(config=None):
|
|||
template_folder=get_template_static_folder("templates"),
|
||||
static_folder=get_template_static_folder("static"),
|
||||
)
|
||||
app.tor_service_id = None
|
||||
app.tor_enabled = False
|
||||
app.jinja_env.autoescape = select_autoescape(default_for_string=True, default=True)
|
||||
logger.info(f"Configuration: {config}")
|
||||
app.config.from_object(config)
|
||||
|
|
@ -255,12 +257,12 @@ def init_app(app: SpecterFlask, hwibridge=False, specter=None):
|
|||
return app
|
||||
|
||||
|
||||
def create_and_init():
|
||||
def create_and_init(config="cryptoadvance.specter.config.ProductionConfig"):
|
||||
"""This method can be used to fill the FLASK_APP-env variable like
|
||||
export FLASK_APP="src/cryptoadvance/specter/server:create_and_init()"
|
||||
See Development.md to use this for debugging
|
||||
"""
|
||||
app = create_app()
|
||||
app.app_context().push()
|
||||
init_app(app)
|
||||
app = create_app(config)
|
||||
with app.app_context():
|
||||
init_app(app)
|
||||
return app
|
||||
|
|
|
|||
|
|
@ -108,9 +108,7 @@
|
|||
{% include "includes/language/language_select.jinja" %}
|
||||
</div>
|
||||
<h1 style="font-size: 1.8em; line-height: 1em;">
|
||||
|
||||
{{ _('Welcome to Specter Desktop') }}
|
||||
|
||||
{{ _('Welcome to Specter Desktop') }}
|
||||
</h1>
|
||||
{% if ('://localhost:' not in url_for('index', _external=True) and '://127.0.0.1:' not in url_for('index', _external=True)) and specter.hwi_bridge_url != "http://127.0.0.1:25441/hwi/api/" %}
|
||||
<div style="margin: auto; display: block;">
|
||||
|
|
@ -261,6 +259,7 @@
|
|||
<a href="https://github.com/cryptoadvance/" target="_blank"><img src="{{ url_for('static', filename='img/github.svg') }}" style="width: 30px; margin: 10px; position: relative; z-index: 1;"></a>
|
||||
<a href="https://twitter.com/specterwallet/" target="_blank"><img src="{{ url_for('static', filename='img/twitter.svg') }}" style="width: 30px; margin: 10px; position: relative; z-index: 1;"></a>
|
||||
</div>
|
||||
<span style="font-size: 0.8em;">uid: {{ specter.config_manager.data["uid"] }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -116,7 +116,6 @@ class VersionChecker:
|
|||
NewConnectionError,
|
||||
) as e:
|
||||
logger.error(f"{e} while checking for new pypi version")
|
||||
raise SpecterError("Muuh")
|
||||
except Exception as e:
|
||||
logger.exception(e)
|
||||
latest = "unknown"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue