Hide keyboard shortcuts

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 

10 

11 

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. 

29 

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 

52 

53 .. cmdref:: 

54 :title: Creates a local web-application with very simple authentification 

55 :cmd: -m mathenjeu static_local --help 

56 

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:: 

61 

62 python -m mathenjeu static_local --cookie_key=dummypwd --start=1 --port=8889 --userpwd=abc --content=display_name,local_folder 

63 

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") 

70 

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)) 

77 

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 

92 

93 

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. 

115 

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 

151 

152 .. cmdref:: 

153 :title: Creates a https static web-application with authentification 

154 :cmd: -m mathenjeu local_https --help 

155 

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:: 

160 

161 python -m mathenjeu local_https 

162 

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 ''") 

168 

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)) 

175 

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)) 

198 

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 

228 

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) 

235 

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