"""
Starts an app locally to test it.
:githublink:`%|py|5`
"""
import os
import sys
import uvicorn
from ..apps import StaticApp
from ..apps.server import ServerHypercorn
[docs]def create_static_local_app(
# log parameters
secret_log=None,
folder='.',
# authentification parameters
max_age=14 * 24 * 60 * 60,
cookie_key=None, cookie_name="mathenjeu",
cookie_domain="127.0.0.1", cookie_path="/",
# content parameters
content=None,
# application parameters
title="Web Application MathEnJeu", short_title="MathEnJeu",
page_doc="http://www.xavierdupre.fr/app/mathenjeu/helpsphinx/",
secure=False, port=8868, middles=None, start=False,
userpwd=None, debug=False, fLOG=print):
"""
Creates a local web-application with very simple authentification.
:param secret_log: to encrypt log (None to ignore)
:param folder: folder where to write the logs (None to disable the logging)
:param max_age: cookie's duration in seconds
:param cookie_key: to encrypt information in the cookie (cannot be None)
:param cookie_name: name of the session cookie
:param cookie_domain: cookie is valid for this path only, also defines the
domain of the web app (its url)
:param cookie_path: path of the cookie once storeds
:param secure: use secured connection for cookies
:param content: list tuple ``route, folder`` to server or a string
``route1,folder1;route2,folder2;...``
:param title: title
:param short_title: short application title
:param page_doc: page documentation (default is :epkg:`mathenjeu`)
:param port: port to deploy the application
:param middles: middles ware, list of couple ``[(class, **kwargs)]``
where *kwargs* are the parameter constructor
:param start: starts the application with :epkg:`uvicorn`
:param userpwd: users are authentified with any alias but a common password
:param debug: display debug information (:epkg:`starlette` option)
:param fLOG: logging function
:return: :class:`StaticApp <mathenjeu.apps.staticapp.staticsite.StaticApp>`
.. cmdref::
:title: Creates a local web-application with very simple authentification
:cmd: -m mathenjeu static_local --help
The command line runs a web application meant to be local
as there is not *https* involved. It serves static content.
The web app relies on :epkg:`starlette`, the server relies
on :epkg:`uvicorn`. Example of use::
python -m mathenjeu static_local --cookie_key=dummypwd --start=1 --port=8889 --userpwd=abc --content=display_name,local_folder
With that application, every user can login with a unique password *abc*.
:githublink:`%|py|65`
"""
if secret_log == '':
raise ValueError("secret_log must be not empty or None, not ''")
if fLOG:
fLOG("[create_static_local_app] create")
if isinstance(content, str):
if fLOG: # pragma: no cover
fLOG("[create_static_local_app] parsing '{0}'".format(content))
content = [tuple(ct.split(',')) for ct in content.split(';')]
if fLOG: # pragma: no cover
fLOG("[create_static_local_app] int {0}".format(content))
app = StaticApp(secret_log=secret_log, middles=middles,
folder=folder, max_age=max_age,
cookie_key=cookie_key, cookie_name=cookie_name,
cookie_domain=cookie_domain, cookie_path=cookie_path,
title=title, short_title=short_title, content=content,
secure=secure, page_doc=page_doc, userpwd=userpwd)
if start:
if fLOG: # pragma: no cover
fLOG(
"[create_static_local_app] start server 'http://{0}:{1}'".format(cookie_domain, port))
uvicorn.run(app.app, host=cookie_domain, port=port,
log_level="debug" if debug else "info",
access_log=True)
return app
[docs]def create_static_https_app(
# log parameters
secret_log=None,
folder='.',
# authentification parameters
max_age=14 * 24 * 60 * 60,
cookie_key=None, cookie_name="mathenjeu",
cookie_domain="127.0.0.1", cookie_path="/",
# application parameters
title="Web Application MathEnJeu", short_title="MathEnJeu",
page_doc="http://www.xavierdupre.fr/app/mathenjeu/helpsphinx/",
secure=False, port=8868, middles=None, start=False,
userpwd=None, debug=False, content=None,
# hypercorn parameters
access_log="-",
access_log_format="%(h)s %(r)s %(s)s %(b)s %(D)s",
ca_certs=None, certfile=None, error_log='-',
keep_alive=600, keyfile=None, root_path='', workers=1,
reload=False, ciphers="ECDHE+AESGCM", fLOG=print):
"""
Creates a https web-application with https authentification.
:param secret_log: to encrypt log (None to ignore)
:param folder: folder where to write the logs (None to disable the logging)
:param max_age: cookie's duration in seconds
:param cookie_key: to encrypt information in the cookie (cannot be None)
:param cookie_name: name of the session cookie
:param cookie_domain: cookie is valid for this path only, also defines the
domain of the web app (its url)
:param cookie_path: path of the cookie once storeds
:param secure: use secured connection for cookies
:param title: title
:param short_title: short application title
:param page_doc: page documentation (default is 'http://www.xavierdupre.fr/app/mathenjeu/helpsphinx')
:param port: port to deploy the application
:param middles: middles ware, list of couple ``[(class, **kwargs)]``
where *kwargs* are the parameter constructor
:param start: starts the application with :epkg:`uvicorn`
:param userpwd: users are authentified with any alias but a common password
:param debug: display debug information (:epkg:`starlette` option)
:param content: list tuple ``route, folder`` to server or a string
``route1,folder1;route2,folder2;...``
:param access_log: The target location for the access log, use - for stdout.
:param access_log_format: The log format for the access log, see help docs,
see `Logging <https://pgjones.gitlab.io/hypercorn/logging.html>`_.
:param ca_certs: Path to the SSL CA certificate file.
:param certfile: Path to the SSL certificate file.
:param ciphers: Ciphers to use for the SSL setup, the default can be found at
`config.py <https://github.com/pgjones/hypercorn/blob/master/hypercorn/config.py#L32>`_
:param error_log: The target location for the error log, use - for stderr.
:param keep_alive: Seconds to keep inactive connections alive for.
:param keyfile: Path to the SSL key file
:param root_path: The setting for the ASGI root_path variable.
:param workers: The number of workers to spawn and use.
:param reload: Enable automatic reloads on code changes.
:param fLOG: logging function
:return: :class:`StaticApp <mathenjeu.apps.staticapp.staticsite.StaticApp>`
.. cmdref::
:title: Creates a https static web-application with authentification
:cmd: -m mathenjeu local_https --help
The command line runs a web application meant to be local
as there is not :epkg:`https` involved. It servers static content.
The web app relies on :epkg:`starlette`, the server relies
on :epkg:`hypercorn`. Example::
python -m mathenjeu local_https
With that application, every user can login with a unique password *abc*.
:githublink:`%|py|164`
"""
if secret_log == '':
raise ValueError( # pragma: no cover
"secret_log must be not empty or None, not ''")
if isinstance(content, str):
if fLOG: # pragma: no cover
fLOG("[create_static_https_app] parsing '{0}'".format(content))
content = [tuple(ct.split(',')) for ct in content.split(';')]
if fLOG: # pragma: no cover
fLOG("[create_static_https_app] int {0}".format(content))
kwargs = dict(secret_log=secret_log, middles=middles,
folder=folder, max_age=max_age,
cookie_key=cookie_key, cookie_name=cookie_name,
cookie_domain=cookie_domain, cookie_path=cookie_path,
title=title, short_title=short_title,
secure=secure, debug=debug, content=content,
page_doc=page_doc, userpwd=userpwd)
app = StaticApp(**kwargs)
if app.app is None:
raise RuntimeError("Unable to create a starlette application.")
if fLOG:
fLOG("[create_static_https_app] app is created")
rows = []
rows.append('"Creates a starlette application."')
rows.append("from mathenjeu.apps import StaticApp")
rows.append("kwargs = " + str(kwargs))
rows.append("app = StaticApp(**kwargs).app")
name = os.path.join(folder, "apphyper.py")
with open(name, "w", encoding="utf-8") as f:
f.write("\n".join(rows))
if fLOG:
fLOG("[create_static_https_app] saved file '{0}'".format(name))
binds = "{0}:{1}".format(cookie_domain, port)
folder = os.path.abspath(folder)
sys.path.append(folder)
try:
import apphyper # pylint: disable=C0415
pa = apphyper.app
if pa is None:
raise RuntimeError("pa should not be None")
except ImportError as e:
# For unit test purposes.
from .. import __file__ as mejfile
main_folder = os.path.abspath(os.path.dirname(mejfile))
main_folder = os.path.normpath(os.path.join(main_folder, ".."))
if main_folder not in sys.path:
sys.path.append(main_folder)
try:
import apphyper # pylint: disable=C0415
pa = apphyper.app
if pa is None:
raise RuntimeError( # pylint: disable=W0707
"pa should not be None")
except ImportError as e:
raise ImportError(
"Unable to import 'apphyper' from '{0}'\n--sys.path--\n{1}".format(
folder, "\n".join(sys.path))) from e
else:
raise ImportError(
"Unable to import 'apphyper' from '{0}'\nFolder '{1}' already present.\n--sys.path--\n{2}".format(
folder, main_folder, "\n".join(sys.path))) from e
application_path = "apphyper:app"
kwargs = dict(application_path=application_path, access_log=access_log,
access_log_format=access_log_format, binds=binds,
ca_certs=ca_certs, certfile=certfile, debug=debug, error_log=error_log,
keep_alive=keep_alive, keyfile=keyfile, root_path=root_path, workers=workers,
reload=reload, ciphers=ciphers)
if fLOG:
fLOG("[create_static_https_app] create server")
server = ServerHypercorn(**kwargs)
if start:
if fLOG:
fLOG(
"[create_static_https_app] starts server on '{0}'".format(binds))
server.run()
while folder in sys.path:
del sys.path[sys.path.index(folder)]
return server