Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2@file
3@brief Starts an app locally to test it.
4"""
5import os
6import sys
7import uvicorn
8from ..apps import StaticApp
9from ..apps.server import ServerHypercorn
12def create_static_local_app(
13 # log parameters
14 secret_log=None,
15 folder='.',
16 # authentification parameters
17 max_age=14 * 24 * 60 * 60,
18 cookie_key=None, cookie_name="mathenjeu",
19 cookie_domain="127.0.0.1", cookie_path="/",
20 # content parameters
21 content=None,
22 # application parameters
23 title="Web Application MathEnJeu", short_title="MathEnJeu",
24 page_doc="http://www.xavierdupre.fr/app/mathenjeu/helpsphinx/",
25 secure=False, port=8868, middles=None, start=False,
26 userpwd=None, debug=False, fLOG=print):
27 """
28 Creates a local web-application with very simple authentification.
30 :param secret_log: to encrypt log (None to ignore)
31 :param folder: folder where to write the logs (None to disable the logging)
32 :param max_age: cookie's duration in seconds
33 :param cookie_key: to encrypt information in the cookie (cannot be None)
34 :param cookie_name: name of the session cookie
35 :param cookie_domain: cookie is valid for this path only, also defines the
36 domain of the web app (its url)
37 :param cookie_path: path of the cookie once storeds
38 :param secure: use secured connection for cookies
39 :param content: list tuple ``route, folder`` to server or a string
40 ``route1,folder1;route2,folder2;...``
41 :param title: title
42 :param short_title: short application title
43 :param page_doc: page documentation (default is :epkg:`mathenjeu`)
44 :param port: port to deploy the application
45 :param middles: middles ware, list of couple ``[(class, **kwargs)]``
46 where *kwargs* are the parameter constructor
47 :param start: starts the application with :epkg:`uvicorn`
48 :param userpwd: users are authentified with any alias but a common password
49 :param debug: display debug information (:epkg:`starlette` option)
50 :param fLOG: logging function
51 :return: @see cl StaticApp
53 .. cmdref::
54 :title: Creates a local web-application with very simple authentification
55 :cmd: -m mathenjeu static_local --help
57 The command line runs a web application meant to be local
58 as there is not *https* involved. It serves static content.
59 The web app relies on :epkg:`starlette`, the server relies
60 on :epkg:`uvicorn`. Example of use::
62 python -m mathenjeu static_local --cookie_key=dummypwd --start=1 --port=8889 --userpwd=abc --content=display_name,local_folder
64 With that application, every user can login with a unique password *abc*.
65 """
66 if secret_log == '':
67 raise ValueError("secret_log must be not empty or None, not ''")
68 if fLOG:
69 fLOG("[create_static_local_app] create")
71 if isinstance(content, str):
72 if fLOG: # pragma: no cover
73 fLOG("[create_static_local_app] parsing '{0}'".format(content))
74 content = [tuple(ct.split(',')) for ct in content.split(';')]
75 if fLOG: # pragma: no cover
76 fLOG("[create_static_local_app] int {0}".format(content))
78 app = StaticApp(secret_log=secret_log, middles=middles,
79 folder=folder, max_age=max_age,
80 cookie_key=cookie_key, cookie_name=cookie_name,
81 cookie_domain=cookie_domain, cookie_path=cookie_path,
82 title=title, short_title=short_title, content=content,
83 secure=secure, page_doc=page_doc, userpwd=userpwd)
84 if start:
85 if fLOG: # pragma: no cover
86 fLOG(
87 "[create_static_local_app] start server 'http://{0}:{1}'".format(cookie_domain, port))
88 uvicorn.run(app.app, host=cookie_domain, port=port,
89 log_level="debug" if debug else "info",
90 access_log=True)
91 return app
94def create_static_https_app(
95 # log parameters
96 secret_log=None,
97 folder='.',
98 # authentification parameters
99 max_age=14 * 24 * 60 * 60,
100 cookie_key=None, cookie_name="mathenjeu",
101 cookie_domain="127.0.0.1", cookie_path="/",
102 # application parameters
103 title="Web Application MathEnJeu", short_title="MathEnJeu",
104 page_doc="http://www.xavierdupre.fr/app/mathenjeu/helpsphinx/",
105 secure=False, port=8868, middles=None, start=False,
106 userpwd=None, debug=False, content=None,
107 # hypercorn parameters
108 access_log="-",
109 access_log_format="%(h)s %(r)s %(s)s %(b)s %(D)s",
110 ca_certs=None, certfile=None, error_log='-',
111 keep_alive=600, keyfile=None, root_path='', workers=1,
112 reload=False, ciphers="ECDHE+AESGCM", fLOG=print):
113 """
114 Creates a https web-application with https authentification.
116 :param secret_log: to encrypt log (None to ignore)
117 :param folder: folder where to write the logs (None to disable the logging)
118 :param max_age: cookie's duration in seconds
119 :param cookie_key: to encrypt information in the cookie (cannot be None)
120 :param cookie_name: name of the session cookie
121 :param cookie_domain: cookie is valid for this path only, also defines the
122 domain of the web app (its url)
123 :param cookie_path: path of the cookie once storeds
124 :param secure: use secured connection for cookies
125 :param title: title
126 :param short_title: short application title
127 :param page_doc: page documentation (default is 'http://www.xavierdupre.fr/app/mathenjeu/helpsphinx')
128 :param port: port to deploy the application
129 :param middles: middles ware, list of couple ``[(class, **kwargs)]``
130 where *kwargs* are the parameter constructor
131 :param start: starts the application with :epkg:`uvicorn`
132 :param userpwd: users are authentified with any alias but a common password
133 :param debug: display debug information (:epkg:`starlette` option)
134 :param content: list tuple ``route, folder`` to server or a string
135 ``route1,folder1;route2,folder2;...``
136 :param access_log: The target location for the access log, use - for stdout.
137 :param access_log_format: The log format for the access log, see help docs,
138 see `Logging <https://pgjones.gitlab.io/hypercorn/logging.html>`_.
139 :param ca_certs: Path to the SSL CA certificate file.
140 :param certfile: Path to the SSL certificate file.
141 :param ciphers: Ciphers to use for the SSL setup, the default can be found at
142 `config.py <https://github.com/pgjones/hypercorn/blob/master/hypercorn/config.py#L32>`_
143 :param error_log: The target location for the error log, use - for stderr.
144 :param keep_alive: Seconds to keep inactive connections alive for.
145 :param keyfile: Path to the SSL key file
146 :param root_path: The setting for the ASGI root_path variable.
147 :param workers: The number of workers to spawn and use.
148 :param reload: Enable automatic reloads on code changes.
149 :param fLOG: logging function
150 :return: @see cl StaticApp
152 .. cmdref::
153 :title: Creates a https static web-application with authentification
154 :cmd: -m mathenjeu local_https --help
156 The command line runs a web application meant to be local
157 as there is not :epkg:`https` involved. It servers static content.
158 The web app relies on :epkg:`starlette`, the server relies
159 on :epkg:`hypercorn`. Example::
161 python -m mathenjeu local_https
163 With that application, every user can login with a unique password *abc*.
164 """
165 if secret_log == '':
166 raise ValueError( # pragma: no cover
167 "secret_log must be not empty or None, not ''")
169 if isinstance(content, str):
170 if fLOG: # pragma: no cover
171 fLOG("[create_static_https_app] parsing '{0}'".format(content))
172 content = [tuple(ct.split(',')) for ct in content.split(';')]
173 if fLOG: # pragma: no cover
174 fLOG("[create_static_https_app] int {0}".format(content))
176 kwargs = dict(secret_log=secret_log, middles=middles,
177 folder=folder, max_age=max_age,
178 cookie_key=cookie_key, cookie_name=cookie_name,
179 cookie_domain=cookie_domain, cookie_path=cookie_path,
180 title=title, short_title=short_title,
181 secure=secure, debug=debug, content=content,
182 page_doc=page_doc, userpwd=userpwd)
183 app = StaticApp(**kwargs)
184 if app.app is None:
185 raise RuntimeError("Unable to create a starlette application.")
186 if fLOG:
187 fLOG("[create_static_https_app] app is created")
188 rows = []
189 rows.append('"Creates a starlette application."')
190 rows.append("from mathenjeu.apps import StaticApp")
191 rows.append("kwargs = " + str(kwargs))
192 rows.append("app = StaticApp(**kwargs).app")
193 name = os.path.join(folder, "apphyper.py")
194 with open(name, "w", encoding="utf-8") as f:
195 f.write("\n".join(rows))
196 if fLOG:
197 fLOG("[create_static_https_app] saved file '{0}'".format(name))
199 binds = "{0}:{1}".format(cookie_domain, port)
200 folder = os.path.abspath(folder)
201 sys.path.append(folder)
202 try:
203 import apphyper # pylint: disable=C0415
204 pa = apphyper.app
205 if pa is None:
206 raise RuntimeError("pa should not be None")
207 except ImportError as e:
208 # For unit test purposes.
209 from .. import __file__ as mejfile
210 main_folder = os.path.abspath(os.path.dirname(mejfile))
211 main_folder = os.path.normpath(os.path.join(main_folder, ".."))
212 if main_folder not in sys.path:
213 sys.path.append(main_folder)
214 try:
215 import apphyper # pylint: disable=C0415
216 pa = apphyper.app
217 if pa is None:
218 raise RuntimeError( # pylint: disable=W0707
219 "pa should not be None")
220 except ImportError as e:
221 raise ImportError(
222 "Unable to import 'apphyper' from '{0}'\n--sys.path--\n{1}".format(
223 folder, "\n".join(sys.path))) from e
224 else:
225 raise ImportError(
226 "Unable to import 'apphyper' from '{0}'\nFolder '{1}' already present.\n--sys.path--\n{2}".format(
227 folder, main_folder, "\n".join(sys.path))) from e
229 application_path = "apphyper:app"
230 kwargs = dict(application_path=application_path, access_log=access_log,
231 access_log_format=access_log_format, binds=binds,
232 ca_certs=ca_certs, certfile=certfile, debug=debug, error_log=error_log,
233 keep_alive=keep_alive, keyfile=keyfile, root_path=root_path, workers=workers,
234 reload=reload, ciphers=ciphers)
236 if fLOG:
237 fLOG("[create_static_https_app] create server")
238 server = ServerHypercorn(**kwargs)
239 if start:
240 if fLOG:
241 fLOG(
242 "[create_static_https_app] starts server on '{0}'".format(binds))
243 server.run()
244 while folder in sys.path:
245 del sys.path[sys.path.index(folder)]
246 return server